package com.kingdee.eas.custom.yq.df.app;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.rpc.ServiceException;

import org.apache.log4j.Logger;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.SQLDataException;
import com.kingdee.bos.ctrl.common.util.SectionByteOutputStream;
import com.kingdee.bos.ctrl.common.util.ZipUtil;
import com.kingdee.bos.ctrl.kdf.util.DES;
import com.kingdee.bos.dao.IObjectCollection;
import com.kingdee.bos.dao.IObjectPK;
import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
import com.kingdee.bos.ebservice.EBException;
import com.kingdee.bos.ebservice.EBHeader;
import com.kingdee.bos.ebservice.EBService;
import com.kingdee.bos.ebservice.EBServiceServiceLocator;
import com.kingdee.bos.ebservice.PayBody;
import com.kingdee.bos.ebservice.PayRequest;
import com.kingdee.bos.ebservice.PayResponse;
import com.kingdee.bos.ebservice.PaymentDetail;
import com.kingdee.bos.ebservice.QueryPayRequest;
import com.kingdee.bos.ebservice.QueryPayRequestBody;
import com.kingdee.bos.ebservice.QueryPayResponse;
import com.kingdee.bos.metadata.entity.EntityViewInfo;
import com.kingdee.bos.metadata.entity.FilterInfo;
import com.kingdee.bos.metadata.entity.FilterItemInfo;
import com.kingdee.bos.metadata.entity.SelectorItemCollection;
import com.kingdee.bos.metadata.entity.SelectorItemInfo;
import com.kingdee.bos.metadata.query.util.CompareType;
import com.kingdee.bos.util.BOSUuid;
import com.kingdee.eas.base.permission.UserInfo;
import com.kingdee.eas.basedata.assistant.AccountBankFactory;
import com.kingdee.eas.basedata.assistant.AccountBankInfo;
import com.kingdee.eas.basedata.assistant.CurrencyFactory;
import com.kingdee.eas.basedata.assistant.CurrencyInfo;
import com.kingdee.eas.basedata.assistant.ISettlementType;
import com.kingdee.eas.basedata.assistant.SettlementTypeFactory;
import com.kingdee.eas.basedata.assistant.SettlementTypeInfo;
import com.kingdee.eas.basedata.master.account.AccountViewFactory;
import com.kingdee.eas.basedata.master.account.AccountViewInfo;
import com.kingdee.eas.basedata.master.account.IAccountView;
import com.kingdee.eas.basedata.org.CompanyOrgUnitFactory;
import com.kingdee.eas.basedata.org.CompanyOrgUnitInfo;
import com.kingdee.eas.basedata.org.ICompanyOrgUnit;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.ParameterConfigFactory;
import com.kingdee.eas.custom.ParameterConfigInfo;
import com.kingdee.eas.custom.yq.df.AuxiliaryFunctionFactory;
import com.kingdee.eas.custom.yq.df.BillStatuEnum;
import com.kingdee.eas.custom.yq.df.IAuxiliaryFunction;
import com.kingdee.eas.custom.yq.df.ISubstituting;
import com.kingdee.eas.custom.yq.df.ISubstitutingEntry;
import com.kingdee.eas.custom.yq.df.SubstitutingCollection;
import com.kingdee.eas.custom.yq.df.SubstitutingEntryCollection;
import com.kingdee.eas.custom.yq.df.SubstitutingEntryFactory;
import com.kingdee.eas.custom.yq.df.SubstitutingEntryInfo;
import com.kingdee.eas.custom.yq.df.SubstitutingFactory;
import com.kingdee.eas.custom.yq.df.SubstitutingInfo;
import com.kingdee.eas.custom.yq.df.client.BankLogPrivatePaySendInfo;
import com.kingdee.eas.custom.yq.df.client.BankLogSubstitutingEntrySendInfo;
import com.kingdee.eas.custom.yq.df.client.BankLogSubstitutingSendInfo;
import com.kingdee.eas.custom.yq.util.ConstantValueUtil;
import com.kingdee.eas.custom.yq.util.DateTimeUtil;
import com.kingdee.eas.eqm.common.core.util.backup.FMConstants;
import com.kingdee.eas.fi.cas.BillStatusEnum;
import com.kingdee.eas.fm.be.BEBankFactory;
import com.kingdee.eas.fm.be.BEException;
import com.kingdee.eas.fm.be.BankInterfaceTypeEnum;
import com.kingdee.eas.fm.be.BankLogFacadeFactory;
import com.kingdee.eas.fm.be.BankLogFactory;
import com.kingdee.eas.fm.be.BankLogInfo;
import com.kingdee.eas.fm.be.BankLogTypeEnum;
import com.kingdee.eas.fm.be.BankPayingBillStateEnum;
import com.kingdee.eas.fm.be.FmBeHelper;
import com.kingdee.eas.fm.be.IBEBank;
import com.kingdee.eas.fm.be.IBankLog;
import com.kingdee.eas.fm.be.IBankLogFacade;
import com.kingdee.eas.fm.be.app.BankBaseDataUtil;
import com.kingdee.eas.fm.be.app.BankBatchSalaryService;
import com.kingdee.eas.fm.be.app.BankFacadeHelper;
import com.kingdee.eas.fm.be.app.BankPrivateService;
import com.kingdee.eas.fm.be.app.BankServiceUtil;
import com.kingdee.eas.fm.be.ws.BankAcnt;
import com.kingdee.eas.fm.be.ws.BankServiceException;
import com.kingdee.eas.fm.be.ws.CallerTag;
import com.kingdee.eas.fm.be.ws.Currency;
import com.kingdee.eas.fm.be.ws.PayStateInfo;
import com.kingdee.eas.fm.be.ws.PaymentCheckResult;
import com.kingdee.eas.fm.be.ws.PaymentInfo;
import com.kingdee.eas.fm.be.ws.PaymentState;
import com.kingdee.eas.fm.common.ContextHelperFactory;
import com.kingdee.eas.fm.common.FMHelper;
import com.kingdee.eas.framework.CoreBaseCollection;
import com.kingdee.eas.util.SysUtil;
import com.kingdee.eas.util.client.EASResource;
import com.kingdee.eas.util.client.MsgBox;
import com.kingdee.util.db.SQLUtils;

/**
 * 描述:按单据同步状态,提交银企互联,登银行日记账,手工修改分录状态
 * 
 * @author mmw 日期：2012-9-27
 */
@SuppressWarnings( { "serial", "unused", "unchecked" })
public class SubstitutingControllerBean extends AbstractSubstitutingControllerBean {
	private static Logger logger = Logger.getLogger("com.kingdee.eas.custom.yq.df.app.SubstitutingControllerBean");
	private static ISubstituting ISubstituting = null;
	private static ISubstitutingEntry ISubstitutingEntry = null;
	private static CurrencyInfo currencyInfo = null;
	private static String userId = "";
	private static IBEBank Ibebank = null;
	private static String companyId = "";
	private static CompanyOrgUnitInfo currentCompany = null;
	private static IBankLog banklog = null;
	private static IBankLogFacade bankLogFacade = null;
	private static IAuxiliaryFunction auxiliaryFunction = null;
	// 提交银企的条数
	private static int index = 0;

	/**
	 * 描述：修改源单据是否下推字段为未下推 作者：刘鹏 创建日期：2013-08-01
	 * 
	 * @param ctx
	 * @param id
	 *            代发单ID
	 * @throws BOSException
	 */
	public void updateCancelled(Context ctx, String id, Map map) throws BOSException {
		if (map == null) {
			return;
		}
		// 获取源单据ID集合
		Set set1 = (Set) map.get("idset");
		List idlist = FMHelper.set2List(set1);
		int count = set1.size();
		// 除以size的整倍数
		int num1 = count / 1000;
		// 除以size的余数
		int num2 = count % 1000;
		// 标示num1大于零
		if (count > 1000) {
			// 将count分批次以size为单位数量提交
			for (int i = 0; i < num1; i++) {
				Set setid = new HashSet();
				for (int j = i * 1000; j < 1000 * (i + 1); j++) {
					setid.add(idlist.get(j));
				}
				updateSubCancelled(ctx, map, setid, id);
			}
			// 若余数不为零,则表示除以size有余数,即把剩下的数量单子在此提交
			if (num2 != 0) {
				Set setid = new HashSet();
				for (int i = 1000 * num1; i < count; i++) {
					setid.add(idlist.get(i));
				}
				updateSubCancelled(ctx, map, setid, id);
			}
		} else {
			updateSubCancelled(ctx, map, set1, id);
		}
	}

	/**
	 * 描述：反写代发单源单据已下推字段,将代发单状态更新为已作废&删除银行日记账信息放在一个事务中 作者：刘鹏 创建日期：2013-08-01
	 * 
	 * @param ctx
	 * @param map
	 * @param set1
	 * @throws SQLDataException
	 * @throws BEException
	 */
	private void updateSubCancelled(Context ctx, Map map, Set set1, String sId) throws BOSException {
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			conn = getConnection(ctx);
			// 更新主表代发单//此为?,?,.....
			String ids = SubHelp.setTran2String(set1);
			// “付款日期”“支付方式”“付款银行”“付款账号”“是否下推代发单”
			//工资CFPayDate,CFPayment,CFPaymentbankID,CFPaymentAccount,CFWhesingle
			// 亲情CFPayDate,CFPayType,CFPayBank,CFPayAccountID,CFIscreatePayment
			// 代收CFRemitDate,CFPayment,CFPayingBankID,CFPayingAccountID,
			// CFIsCreateRepBill
			StringBuffer sql = new StringBuffer("");
			if (ConstantValueUtil.TABLE_WAGES.equals(map.get("table"))) {
				// 工资sdl
				sql.append("UPDATE " + map.get("table") + " SET " + map.get("property1") + " = ?," + map.get("property2") + "=''," + map.get("property3") + "='',"
						+ map.get("property4") + "=''," + map.get("property5") + "=''," + map.get("property6") + "='' WHERE FID IN (" + ids + ")");
			} else {
				// 代收货款 亲情1+1
				sql.append("UPDATE " + map.get("table") + " SET " + map.get("property1") + " = ?," + map.get("property2") + "=''," + map.get("property3") + "='',"
						+ map.get("property4") + "=''," + map.get("property5") + "='' WHERE FID IN (" + ids + ")");
			}

			sql.append(";DELETE FROM T_CAS_JOURNAL JOURNAL WHERE JOURNAL.FBILLID=?");
			sql.append(";UPDATE CT_YQ_SUBSTITUTING SET CFCANCELLEDUSERID=?, CFCANCELLEDDATE=? ,CFBillSTATUS=? WHERE FID=?");
			pstmt = conn.prepareStatement(sql.toString());
			pstmt.setString(1, map.get("value").toString());
			// 拼接ids语句,并赋值
			pstmt = SubHelp.setSql(set1, pstmt, 2);

			// 获取当前操作用户
			UserInfo user = ContextHelperFactory.getLocalInstance(ctx).getCurrentUser();
			pstmt.setString(set1.size() + 2, sId);
			pstmt.setString(set1.size() + 2 + 1, user.getString("id"));
			pstmt.setTimestamp(set1.size() + 2 + 2, new Timestamp(new Date().getTime()));
			pstmt.setString(set1.size() + 2 + 3, BillStatuEnum.CANCELLED_VALUE);
			pstmt.setString(set1.size() + 2 + 4, sId);

			int c = pstmt.executeUpdate();

			// // 删除银行日记账
			// String deleteJournalSql=
			// " DELETE FROM T_CAS_JOURNAL JOURNAL WHERE JOURNAL.FBILLID=?";
			// pstmt = conn.prepareStatement(deleteJournalSql);
			// pstmt.setString(1,sId);
			// int a=pstmt.executeUpdate();
			//			
			// // 更新代发单状态为已作废
			// //获取当前操作用户
			// UserInfo
			// user=ContextHelperFactory.getLocalInstance(ctx).getCurrentUser();
			// String updateSubSql=
			// " UPDATE CT_YQ_SUBSTITUTING SET CFCANCELLEDUSERID=?, CFCANCELLEDDATE=? ,CFBillSTATUS=? WHERE FID=?"
			// ;
			// pstmt = conn.prepareStatement(updateSubSql);
			// pstmt.setString(1,user.getString("id"));
			// pstmt.setTimestamp(2,new Timestamp(new Date().getTime()));
			// pstmt.setString(3,BillStatuEnum.CANCELLED_VALUE);
			// pstmt.setString(4, sId);
			// int b=pstmt.executeUpdate();pstmt.executeBatch();

		} catch (SQLException e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				throw new BOSException(e1.getMessage());
			}
			throw new BOSException(e.getMessage());
		} finally {
			SQLUtils.cleanup(null, pstmt, conn);
		}
	}

	/**
	 * 描述：提交银企互联, 作者：mmw 创建日期：2012-12-5-上午10:12:50
	 * 
	 * @see com.kingdee.eas.custom.yq.df.app.AbstractSubstitutingControllerBean#pay(com.kingdee.bos.Context,
	 *      java.lang.String)
	 * @param ctx
	 * @param url银企平台地址
	 *            ，可不传，从参数配置中读取
	 * @param idSet代发单主表id
	 * @throws BOSException
	 */
	public void pay(Context ctx, String url, Set idSet, String computerIP, String computerName) throws BOSException, EASBizException {
		if (idSet.size() > 1)
			throw new BEException(BEException.NOTALLOWBATCHSUBMIT);
		try {
			// 检查银企网关
			FmBeHelper.checkWebService(ctx);
			// 校验科目和或账号是否有效,
			checkIdIsValid(ctx, idSet);
		} catch (Exception e) {
			throw new BEException(BEException.COMMON, new String[] { e.getMessage() });
		}

		ISubstituting subBiz = SubstitutingFactory.getLocalInstance(ctx);
		SelectorItemCollection sele = new SelectorItemCollection();
		sele.add("*");
		sele.add("entrys.*");
		sele.add("payBankNumber.*");
		sele.add("feeType.number");
		sele.add("feeType.name");
		sele.add("entrys.payeeArea.number");
		sele.add("entrys.payeeArea.name");
		sele.add("entrys.payeeArea.deptId");
		sele.add("entrys.payeeCity.name");
		sele.add("entrys.PayBankNumber.*");
		sele.add("entrys.PayBankNumber.bank.*");
		sele.add("entrys.settlementType.*");
		SubstitutingInfo info = subBiz.getSubstitutingInfo(new ObjectUuidPK(idSet.iterator().next().toString()), sele);
		try {
			// 提交
			busiPay(ctx, info, computerIP, computerName);
			// 修改代发单状态
			// 提交银企时间默认为当前时间
			info.setSubmitBankDate(new Date());
			// 是否提交银企为true
			info.setIsSubmitBank(true);
			SelectorItemCollection item = new SelectorItemCollection();
			item.add(new SelectorItemInfo("submitBankDate"));
			item.add(new SelectorItemInfo("isSubmitBank"));
			subBiz.updatePartial(info, item);
		} catch (MalformedURLException e) {
			logger.error("获取中间件地址URL失败 error:" + e.getLocalizedMessage(), e);
			throw new BEException(BEException.COMMON, new String[] { e.getMessage() });
		} catch (RemoteException e) {
			logger.error("Substituting error:" + e.getLocalizedMessage(), e);
			throw new BEException(BEException.COMMON, new String[] { e.getMessage() });
		} catch (ServiceException e) {
			logger.error("Substituting error:" + e.getLocalizedMessage(), e);
			throw new BEException(BEException.COMMON, new String[] { e.getMessage() });
		} catch (Exception e) {
			logger.error("Substituting error:" + e.getLocalizedMessage(), e);
			throw new BEException(BEException.COMMON, new String[] { e.getMessage() });
		}

	}

	/**
	 * 批扣主程序
	 * 
	 * @param ctx
	 * @param computerName
	 * @param computerIP
	 * @param division
	 * @param noPersonMap
	 * @param bankAccountNumber
	 * @param isubcoll
	 *            批扣账户信息
	 * @param bankAccountNumber
	 *            扣款时间
	 * @return String[] [扣款状态][扣款金额][银行返回信息]
	 * @throws MalformedURLException
	 * @throws ServiceException
	 * @throws RemoteException
	 * @throws BOSException
	 * @throws EASBizException
	 */
	public void busiPay(Context ctx, SubstitutingInfo info, String computerIP, String computerName) throws MalformedURLException, ServiceException, RemoteException, BOSException,
			EASBizException {
		// 代发单主表接口
		ISubstituting Isub = SubstitutingFactory.getLocalInstance(ctx);
		// 代发单分录接口
		ISubstitutingEntry IsubEntry = SubstitutingEntryFactory.getLocalInstance(ctx);
		// 代发单辅助功能接口
		IAuxiliaryFunction auxiliaryFunctions = AuxiliaryFunctionFactory.getLocalInstance(ctx);
		SubHelp subhelp = new SubHelp();
		PayRequest request = new PayRequest();
		PayBody body = new PayBody();
		// 付款账号
		String bankAccountNumber = info.getPayBankNumber().getBankAccountNumber();
		// 代发单分录集合
		SubstitutingEntryCollection isubcoll = info.getEntrys();
		// 主要代发单的分录提交银企互联条数
		PaymentDetail[] details = new PaymentDetail[isubcoll.size()];
		EBHeader header = new EBHeader();
		// 整批的扣款时间
		Date batchTime = new Date();

		// 保存主表唯一标示,为按单据同步状态用的唯一有用参数
		//info.setBatchSeqID(bankAccountNumber+DateTimeUtil.formatyyyyMMddHHmmss
		// (batchTime));

		// start edit by maomingwu 20130713 更改单据主表唯一标识,只允许数字或字母组成
		String number = info.getNumber().replaceAll("-", "");
		info.setBatchSeqID(number);
		// end edit by maomingwu 20130713 更改单据主表唯一标识

		SelectorItemCollection items = new SelectorItemCollection();
		items.add(new SelectorItemInfo("BatchSeqID"));
		Isub.updatePartial(info, items);

		// 收付类别
		String feetypeNumber = info.getFeeType().getNumber();
		String feetypeName = info.getFeeType().getName();
		BigDecimal totalAmounts = new BigDecimal(0);

		for (int i = 0; i < isubcoll.size(); i++) {
			SubstitutingEntryInfo iaInfo = isubcoll.get(i);
			if (iaInfo != null && iaInfo.getPayeeBank() != null) {
				totalAmounts = totalAmounts.add(iaInfo.getAmount());
				// 记录批扣时间
				Date incomeTime = new Date();
				// 设置details
				details[i] = new PaymentDetail();
				// 不能重复。ERP系统用于标识一笔支付请求的唯一ID，表示该笔支付要求银企中间件执行一次转发。
				// details[i].setDetailSeqID(i+"SEQID"+iaInfo.getPayeeNumber()+
				// incomeTime.getTime());

				// start edit by maomingwu 20130713 更改单据分录唯一标识
				details[i].setDetailSeqID(i + "SEQID" + number);
				// end edit by maomingwu 20130713 更改单据分录唯一标识

				// 可以重复。ERP系统用于标识一笔业务支付的唯一ID。业务要求该笔支付成功到账。
				//如果失败了，需要重新付款，这时，detailBizNo不变，采用新的detailSeqID，将支付数据重新提交给银企中间件。
				// 银企中间件将两次付款理解为不同的付款。
				// details[i].setDetailBizNo(i+"BIZNO"+iaInfo.getPayeeNumber()+
				// incomeTime.getTime());

				// start edit by maomingwu 20130713 更改单据唯一标识
				details[i].setDetailBizNo(i + "BIZNO" + number);
				// end edit by maomingwu 20130713 更改单据主表唯一标识

				// 收款帐号(代扣时为扣款账号，也即营业部对应的账号)
				details[i].setPayeeAccNo(iaInfo.getPayeeNumber());
				// 收款帐户名称
				details[i].setPayeeAccName(iaInfo.getPayeeName());

				boolean var = false;
				// 结算方式
				if (iaInfo.getSettlementType() != null && !iaInfo.getSettlementType().equals("")) {
					// true 对私 false 对公
					var = iaInfo.getSettlementType().isIsPersonPay();
				}
				// 收款方类型：company表示企业账户 individual表示个人账户
				// 对私
				if (var) {
					details[i].setPayeeType("individual");// 对私
				} else {
					details[i].setPayeeType("company");// 对公
				}

				// 收款人开户银行全称：如工商银行
				details[i].setPayeeBankName(iaInfo.getPayeeBank());
				// 收款开户行地址：如深圳
				details[i].setPayeeBankAddr(iaInfo.getPayeeCity().getName());
				// 国家：默认中国
				details[i].setPayeeCountry("中国");
				// 省份
				details[i].setPayeeProvince(iaInfo.getPayeeProvince());
				// 城市
				details[i].setPayeeCity(iaInfo.getPayeeCity().getName());
				// 地区代码
				// details[i].setPayeeAreaCode(entry.getAreaName());
				// CNAPS号：跨行必填
				details[i].setPayeeCnapsCode("");
				// 每一笔的付款金额：金额数字；必须是正数；精确到百分位
				BigDecimal amount = iaInfo.getAmount().setScale(2, BigDecimal.ROUND_HALF_UP);
				details[i].setAmount(amount.toString());
				// 加急标志：true 表示加急;false 表示不加急
				details[i].setUrgent("true");
				// 是否强制落地：个别银行，比如工行，有些特殊支付业务，即使是同行支付仍要求银行落地处理。（暂未使用）
				details[i].setForceManual("false");
				// 银企中间件付款用途,都填-1
				details[i].setUseCode("-1");
				// 用途类型：工资（对私）、佣金（对私）、网上报销（对公对私）、杂费（对公对私）、资金上划、资金下拨、保险理赔支付。
				// 跟对公对私分类有关；跟银行对账的纸质回单中分类有关，具体要向银行咨询
				details[i].setUse("业务支付");
				// 付款说明：说明是哪个收付类别,此字段没有很大作用

				// start edit by xuwei 更改付款说明传入值
				// details[i].setDesc(feetypeName);
				// 1.代收货款出账银行摘要为“代收货款”改为“代收+单号”
				if (feetypeNumber.equals(ConstantValueUtil.REMITREFUNDBILL)) {
					details[i].setDesc("代" + iaInfo.getDetailNumber());
				}
				// 2.亲情1+1出账银行摘要为“亲情1+1”改为“亲情+工号”
				if (feetypeNumber.equals(ConstantValueUtil.KINGSHIPBILL) || feetypeNumber.equals(ConstantValueUtil.KINGSHIPBILLN)) {
					details[i].setDesc("亲情" + iaInfo.getDetailNumber());
				}
				// 3.工资出账银行摘要为“工资”改为“工资+工号”
				if (feetypeNumber.equals(ConstantValueUtil.WAGES) || feetypeNumber.equals(ConstantValueUtil.WAGESN)) {
					details[i].setDesc("工资" + iaInfo.getDetailNumber());
				}
				// end edit by xuwei 更改付款说明传入值

				// 验证字段
				details[i].setVerifyField(DES.encode(iaInfo.getPayeeNumber() + iaInfo.getAmount().toString()));
				// 预留字段一：true表示并笔入账，false表示逐笔入账。选true测试时，无明细
				details[i].setReserved1("false");
				// //预留字段二：缴费编号，用于工行收款（代扣）
				// details[i].setReserved2("201211010001");
				// //预留字段三：协议编号 ，用于工行收款（代扣）
				// details[i].setReserved3("BDP300086068");

				// 分录唯一标识,为按单据同步状态准备
				// iaInfo.setSerialNumber(i+"SEQID"+iaInfo.getPayeeNumber()+
				// incomeTime.getTime());

				// start edit by maomingwu 20130713 更改分录唯一标示
				iaInfo.setSerialNumber(i + "SEQID" + number);
				// end edit by maomingwu 20130713 更改分录唯一标识

				SelectorItemCollection item = new SelectorItemCollection();
				item.add(new SelectorItemInfo("serialNumber"));
				IsubEntry.updatePartial(iaInfo, item);
			}
		}

		// 设置header
		// 客户端软件：调用银企中间件系统缩写名称
		header.setClientName("EAS");
		// 客户端版本：调用银企中间件系统的版本信息
		header.setClientVersion("EAS7.0");
		// 消息类型：request 表示请求；response 表示响应；默认为请求
		header.setMessageType("request");
		// 业务类型：pay表示支付类业务
		header.setBizType("pay");
		String paybankName = info.getPayerBank();
		// 业务子类型：收款（代扣），用income表示
		/**
		 * 1.代发工资，用pay_for_salary表示（对私）； 3.普通支付，用pay表示，目前用于其余用途的支付（对公对私）。
		 **/
		if (feetypeNumber.equals(ConstantValueUtil.WAGES) && paybankName.indexOf("工商") != -1) {
			// 工资同行
			header.setSubBizType("pay_for_salary");
		} else if (feetypeNumber.equals(ConstantValueUtil.WAGES) && paybankName.indexOf("工商") == -1) {
			// 工资同行 //不为工商
			header.setSubBizType("pay");
		} else if (feetypeNumber.equals(ConstantValueUtil.WAGESN) || feetypeNumber.equals(ConstantValueUtil.KINGSHIPBILLN)
				|| feetypeNumber.equals(ConstantValueUtil.REMITREFUNDBILL) || feetypeNumber.equals(ConstantValueUtil.KINGSHIPBILL)) {
			// 工资跨行-亲情1+1跨行-亲情1+1同行-代收货款
			header.setSubBizType("pay");
		}
		// 操作名称：支付类业务(pay)有两种操作：支付，用pay表示；支付结果查询,用queryPay表示
		header.setOperationName("pay");
		// 币别：CNY表示人民币
		header.setCurrency("CNY");
		// 主账号：含义为查询帐号或付款帐号
		header.setAccNo(bankAccountNumber);
		// 请求时间：格式为yyyyMMddHHmmss
		header.setRequestTime(DateTimeUtil.formatyyyyMMddHHmmss(batchTime));

		// 设置body
		// 不能重复。ERP系统（接入第三方系统产生）用于标识一批支付请求的唯一ID，表示该批次支付要求银企中间件执行一次转发。
		//body.setBatchSeqID(bankAccountNumber+DateTimeUtil.formatyyyyMMddHHmmss
		// (batchTime));

		// start edit by maomingwu 20130713 更改唯一值，与主表统一
		body.setBatchSeqID(number);
		// end edit by maomingwu 20130713 更改唯一值，与主表统一

		// 总笔数
		body.setTotalCount(String.valueOf(isubcoll.size()));
		// 总金额，精确到小数点后两位
		BigDecimal totalamount = totalAmounts.setScale(2, BigDecimal.ROUND_HALF_UP);
		body.setTotalAmount(totalamount.toString());
		// 校验字段：加密字段，需填写任意字符串，现没有实际效果，但必须有值。校验字段=des(总笔数+总金额)
		body.setVerifyField(DES.encode(String.valueOf(isubcoll.size()) + (totalAmounts)));
		// 每一笔支付的明细
		body.setDetails(details);

		// 设置request
		request.setBody(body);
		request.setHeader(header);
		// start edit by maomingwu 20130713 修改及时日志
		logger.info("Substituting info:Pay BatchSeqID " + info.getNumber() + " is ready. Start to send!");
		// start edit by maomingwu 20130713 更改及时日志

		// 获取批扣银企平台地址
		String url = getEBServiceURL(ctx);
		java.net.URL endpoint = new java.net.URL(url);
		EBServiceServiceLocator locator = new EBServiceServiceLocator();
		EBService service = locator.getEBService(endpoint);
		// 返回值
		PayResponse response = null;
		try {
			// 修改代发单状态,提交银企时间,是否提交银企
			updateStateAndTime(info, Isub);
			response = service.pay(request);
		} catch (Exception e) {
			// 反写代发单状态
			SubstitutingInfo subinfo = Isub.getSubstitutingInfo(new ObjectUuidPK(info.getId().toString()));
			reverseSaveForAgentPayBill(ctx, subinfo);
			throw new BEException(BEException.COMMON, new String[] { "中间件返回异常信息为：" + e.getMessage() });
		}

		// 返回异常
		EBException exception = response.getException();
		PayBody responsebody = response.getBody();
		EBHeader responseheader = response.getHeader();
		if (exception == null) {

			//logger.info("Substituting info:Pay BatchSeqID "+bankAccountNumber+
			// DateTimeUtil.formatyyyyMMddHHmmss(batchTime)+ " send success!");
			// start edit by maomingwu 20130713 修改及时日志
			logger.info("Substituting info:Pay BatchSeqID " + info.getNumber() + " send success!");
			// start edit by maomingwu 20130713 更改及时日志

			// exception为null时，表示银企中间件正常响应，请解析body
			PaymentDetail[] reDetails = responsebody.getDetails();
			String[][] entrys_param = new String[reDetails.length][6];
			CoreBaseCollection coll = new CoreBaseCollection();
			for (int h = 0; h < reDetails.length; h++) {
				PaymentDetail detail = reDetails[h];
				// 业务系统用于标识一笔支付的唯一ID，不能重复
				entrys_param[h][0] = detail.getDetailSeqID();// 业务唯一标识
				entrys_param[h][1] = detail.getAmount();
				// EB_PROCESSING:银企中间件处理中;EB_TRANSMIT_FAIL:银企中间件转发失败;
				// BANK_PROCESSING:银行处理中 ;
				// BANK_SUCCESS:银行交易成功;BANK_FAIL:银行交易失败;BANK_EXCEPTION:银行交易异常
				entrys_param[h][2] = detail.getEbStatus();
				// 银企中间件对支付结果的描述
				entrys_param[h][3] = detail.getEbStatusMsg();
				// 银行提供的支付结果的状态码
				entrys_param[h][4] = detail.getBankStatus();
				// 银行提供的支付结果的描述信息
				entrys_param[h][5] = detail.getBankStatusMsg();
				// 更新主表实发金额,实发笔数
				// 更新分录银行状态,银行返回信息,是否成功
				BankPayingBillStateEnum state = null;
				boolean isSuccess = false;
				// 扣款状态
				if ("".equals(entrys_param[h][2])) {
					// 批扣已发起
					state = BankPayingBillStateEnum.DE;
				} else if ("EB_PROCESSING".equals(entrys_param[h][2])) {
					// 准备提交
					state = BankPayingBillStateEnum.OS;
				} else if ("BANK_PROCESSING".equals(entrys_param[h][2])) {
					// 提交成功
					state = BankPayingBillStateEnum.OS;
				} else if ("BANK_SUCCESS".equals(entrys_param[h][2])) {
					// 交易成功
					state = BankPayingBillStateEnum.TS;
					isSuccess = true;
				} else if ("BANK_FAIL".equals(entrys_param[h][2])) {
					// 交易失败
					state = BankPayingBillStateEnum.TF;
				} else if ("BANK_EXCEPTION".equals(entrys_param[h][2])) {
					// 交易未确认
					state = BankPayingBillStateEnum.NC;
				} else if ("EB_TRANSMIT_FAIL".equals(entrys_param[h][2])) {
					// 提交失败
					state = BankPayingBillStateEnum.OF;
				}
				// 更新主表实发金额,实发笔数
				// 更新分录银行状态,银行返回信息,是否成功
				Connection conn = null;
				PreparedStatement pstmt = null;
				try {
					conn = getConnection(ctx);
					// 更新分录银行状态和银行返回信息，并且更新是否成功字段
					String sql = "Update CT_YQ_SubstitutingEntry set CFBankStatus = ?,CFBankReturnInfo = ?,CFIsSucceed = ? where CFSERIALNUMBER  = ? ";
					pstmt = conn.prepareStatement(sql);
					pstmt.setInt(1, state.getValue());
					pstmt.setString(2, entrys_param[h][3] + entrys_param[h][4] + entrys_param[h][5]);
					pstmt.setBoolean(3, isSuccess);
					pstmt.setString(4, entrys_param[h][0]);
					pstmt.executeUpdate();
				} catch (SQLException e) {
					throw new BEException(BEException.WRITESTATEFAILURE);
				} finally {
					SQLUtils.cleanup(null, pstmt, conn);
				}
			}
			// 主要是为跨行调用接口后，重新加载实体，因为实体中分录的状态，和银行返回信息，和流水号已经保存
			EntityViewInfo view = filterViewToAll(info.getId().toString());
			SubstitutingInfo infos = Isub.getSubstitutingCollection(view).get(0);
			// 更新代发单实发金额和实发总数，并更新是否成功字段
			reverseSourceBill(ctx, infos);
			subhelp.LogForAuxiliaryFunction(ctx, infos, InterfaceTypeEnum.SUBMIT, null, auxiliaryFunctions, computerIP, computerName);
			// responsebody.getBatchSeqID();//报账号
			// responsebody.getTotalCount();//总笔数
			// responsebody.getTotalAmount();//总金额
			// responsebody.getVerifyField();//校验字段
		} else if (responsebody == null) {
			//logger.info("Substituting info:Pay BatchSeqID "+bankAccountNumber+
			// DateTimeUtil.formatyyyyMMddHHmmss(batchTime)+
			// " send exception: "+
			// exception.getMessage()+" ,and the time that happens is "
			// +exception.getTime());
			// start edit by maomingwu 20130713 修改及时日志
			logger.info("Substituting info:Pay BatchSeqID " + info.getNumber() + " send exception: " + exception.getMessage() + " ,and the time that happens is "
					+ exception.getTime());
			// start edit by maomingwu 20130713 更改及时日志
		}
		if (exception != null) {
			throw new BEException(BEException.COMMON, new String[] { "中间件返回异常信息为：" + exception.getMessage() });
		}
	}

	/**
	 * 描述：过滤条件 作者：mmw 创建日期：2012-12-7-上午09:34:43
	 * 
	 * @param string
	 * @return
	 */
	private EntityViewInfo filterViewToAll(String id) {
		SubstitutingCollection collection = new SubstitutingCollection();
		FilterInfo filter = new FilterInfo();
		EntityViewInfo view = new EntityViewInfo();
		filter.getFilterItems().add(new FilterItemInfo("id", id, CompareType.EQUALS));
		view.setFilter(filter);
		SelectorItemCollection sele = new SelectorItemCollection();
		sele.add("number");
		sele.add("batchNumber");
		sele.add("feeType.number");
		sele.add("entrys.detailNumber");
		sele.add("entrys.bankStatus");
		sele.add("entrys.bankReturnInfo");
		sele.add("entrys.amount");
		view.setSelector(sele);
		return view;
	}

	/**
	 * 描述：更新状态和提交银企时间 作者：mmw 创建日期：2012-12-7-上午08:32:23
	 * 
	 * @param info
	 * @param Isub
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void updateStateAndTime(SubstitutingInfo info, ISubstituting Isub) throws BOSException, EASBizException {
		// 出纳标志,idSet其实只有一个值,
		SubstitutingInfo infos = Isub.getSubstitutingInfo(new ObjectUuidPK((info.getId().toString())));
		// 单据状态为已付款
		infos.setBillStatus(BillStatuEnum.PAYING);
		// 提交银企时间默认为当前时间
		infos.setSubmitBankDate(new Date());
		// 是否提交银企为true
		infos.setIsSubmitBank(true);
		SelectorItemCollection item = new SelectorItemCollection();
		item.add(new SelectorItemInfo("billStatus"));
		item.add(new SelectorItemInfo("submitBankDate"));
		item.add(new SelectorItemInfo("isSubmitBank"));
		Isub.updatePartial(infos, item);
	}

	/**
	 * 描述：对私对公区分集合 作者：mmw 创建日期：2012-12-5-下午03:20:17
	 * 
	 * @param ctx
	 * @param info
	 * @return
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private Map divisionPayBillTypes(Context ctx, SubstitutingInfo info) throws EASBizException, BOSException {
		Map all = new HashMap();
		// 对公集合
		Map noPersonmao = new HashMap();
		// 对私集合
		Map personmap = new HashMap();
		// 分录集合接口
		SubstitutingEntryCollection coll = info.getEntrys();
		SubstitutingEntryCollection personpaycoll = new SubstitutingEntryCollection();
		SubstitutingEntryCollection nopersonpaycoll = new SubstitutingEntryCollection();
		for (int i = 0; i < coll.size(); i++) {
			SubstitutingEntryInfo entryInfo = coll.get(i);
			BankPayingBillStateEnum state = entryInfo.getBankStatus();
			// 如果分录状态不为空,则表明这条分录数据已经提交银企,不管状态失败或成功,不允许重复提交银企付款
			if (state != null && !state.equals("") && state != BankPayingBillStateEnum.DE) {
				continue;
			}
			// 通过判断结算方式来判断是否对私，若没有，则走对公付款接口
			if (entryInfo.getSettlementType() == null) {
				nopersonpaycoll.add(entryInfo);
				noPersonmao.put("noPersonPay", nopersonpaycoll);
			} else if (entryInfo.getSettlementType().isIsPersonPay()) {
				// 若分录收款账号是对私付款，则将账号信息和分录实体填充到map集合中
				personpaycoll.add(entryInfo);
				personmap.put("personPay", personpaycoll);
			} else {
				// 对公付款，则在此记录
				nopersonpaycoll.add(entryInfo);
				noPersonmao.put("noPersonPay", nopersonpaycoll);
			}
		}
		all.put("personPay", personpaycoll);
		all.put("noPersonPay", nopersonpaycoll);
		return all;
	}

	/**
	 * 描述：更新单据状态,提交银企时间,是否提交银企互联 作者：mmw 创建日期：2012-12-5-下午02:19:54
	 * 
	 * @param ctx
	 * @param info
	 */
	private void reverseSaveForAgentPayBill(Context ctx, SubstitutingInfo info) {
		// 主要回滚单据状态,提交银企时间,是否提交银企互联
		// 单据状态为已审核
		info.setBillStatus(BillStatuEnum.AUDITOR);
		// 提交银企时间为空
		info.setSubmitBankDate(null);
		// 是否提交银企为false
		info.setIsSubmitBank(false);
		SelectorItemCollection item = new SelectorItemCollection();
		item.add(new SelectorItemInfo("billStatus"));
		item.add(new SelectorItemInfo("submitBankDate"));
		item.add(new SelectorItemInfo("isSubmitBank"));
		try {
			SubstitutingFactory.getLocalInstance(ctx).updatePartial(info, item);
		} catch (EASBizException e) {
			e.printStackTrace();
		} catch (BOSException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 描述：按单据同步状态 作者：mmw 创建日期：2012-12-5-下午01:57:50
	 * 
	 * @see com.kingdee.eas.custom.yq.df.app.AbstractSubstitutingControllerBean#_queryPay(com.kingdee.bos.Context,
	 *      java.lang.String, java.util.Set)
	 * @param ctx
	 * @param url
	 * @param idSet
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected void _queryPay(Context ctx, String url, Set idSet, String computerIP, String computerName) throws BOSException, EASBizException {
		EntityViewInfo ev = new EntityViewInfo();
		FilterInfo filter = new FilterInfo();
		filter.getFilterItems().add(new FilterItemInfo("id", new HashSet(idSet), CompareType.INCLUDE));
		ev.setFilter(filter);
		ev.getSelector().add("*");
		ev.getSelector().add("entrys.*");
		ev.getSelector().add("feeType.number");
		ev.getSelector().add("payBankNumber.*");
		ev.getSelector().add("payBankNumber.openArea.*");
		ev.getSelector().add("payBankNumber.bankInterfaceType");
		ev.getSelector().add("entrys.SettlementType.*");

		// 根据id查出代发单集合
		SubstitutingCollection billColl = SubstitutingFactory.getLocalInstance(ctx).getSubstitutingCollection(ev);
		// 对 每一个账户循环更新
		for (int i = 0, size = billColl.size(); i < size; i++) {
			SubstitutingInfo bill = billColl.get(i);
			// if(checkEntryPayState(bill)) continue;
			String feetypeNumber = bill.getFeeType().getNumber();// 收付类别
			String accNo = bill.getPayBankNumber().getBankAccountNumber();// 付款账号
			try {
				String requestTime = DateTimeUtil.formatyyyyMMddHHmmss(new Date());
				busiQueryPay(ctx, bill, accNo, requestTime, feetypeNumber, computerIP, computerName);
			} catch (MalformedURLException e) {
				throw new BEException(BEException.COMMON, new String[] { e.getMessage() });
			} catch (RemoteException e) {
				throw new BEException(BEException.COMMON, new String[] { e.getMessage() });
			} catch (ServiceException e) {
				throw new BEException(BEException.COMMON, new String[] { e.getMessage() });
			}
		}
	}

	/**
	 * 工行批扣结果反馈主程序
	 * 
	 * @param ctx
	 * @param serialNumber
	 *            批扣账户信息
	 * @param accNo
	 *            扣款时间
	 * @param requestTime
	 * @param feetypeNumber
	 * @param computerName
	 * @param computerIP
	 * @return String[] [扣款状态][扣款金额][银行返回信息]
	 */
	public void busiQueryPay(Context ctx, SubstitutingInfo bill, String accNo, String requestTime, String feetypeNumber, String computerIP, String computerName)
			throws MalformedURLException, ServiceException, RemoteException, BOSException, EASBizException {
		// 该数据 的业务唯一标示Id,此值在提交银企时保存的
		if (bill.getBatchSeqID().equals("")) {
			throw new BEException(BEException.COMMON, new String[] { "业务单据唯一标示ID为空,不能够返回银行信息!" });
		}
		String BatchSeqID = bill.getBatchSeqID().toString();// 业务单据唯一标示
		String serialNumber = BatchSeqID;

		// 代发单主表接口
		ISubstituting isub = SubstitutingFactory.getLocalInstance(ctx);
		// 代发单接口
		ISubstitutingEntry isubentry = SubstitutingEntryFactory.getLocalInstance(ctx);

		// 代发单辅助功能接口
		IAuxiliaryFunction auxiliaryFunctions = AuxiliaryFunctionFactory.getLocalInstance(ctx);
		QueryPayRequest request = new QueryPayRequest();
		QueryPayRequestBody body = new QueryPayRequestBody();
		SubHelp subhelp = new SubHelp();
		EBHeader header = new EBHeader();
		// 设置头
		header.setClientName("EAS");
		header.setClientVersion("EAS7.0");
		header.setBizType("pay");
		String paybankName = bill.getPayerBank();
		/**
		 * 1.代发工资，用pay_for_salary表示（对私）； 3.普通支付，用pay表示，目前用于其余用途的支付（对公对私）。
		 **/
		if (feetypeNumber.equals(ConstantValueUtil.WAGES) && paybankName.indexOf("工商") != -1) {
			// 工资同行
			header.setSubBizType("pay_for_salary");
		} else if (feetypeNumber.equals(ConstantValueUtil.WAGES) && paybankName.indexOf("工商") == -1) {
			// 工资同行 //不为工商
			header.setSubBizType("pay");
		} else if (feetypeNumber.equals(ConstantValueUtil.WAGESN) || feetypeNumber.equals(ConstantValueUtil.KINGSHIPBILLN)
				|| feetypeNumber.equals(ConstantValueUtil.REMITREFUNDBILL) || feetypeNumber.equals(ConstantValueUtil.KINGSHIPBILL)) {
			// 工资跨行-亲情1+1跨行-亲情1+1同行-代收货款
			header.setSubBizType("pay");
		}
		header.setOperationName("queryPay");
		// CNY表示人民币，目前只支持人民币
		header.setCurrency("CNY");
		// request表示请求response表示响应
		header.setMessageType("request");
		// 格式为yyyyMMddHHmmss
		header.setRequestTime(requestTime);
		// 主账号 含义为查询帐号或付款帐号
		header.setAccNo(accNo);
		// 设置body
		// 报账号,即ERP产生的批次号,主表唯一标识
		body.setBatchSeqID(serialNumber);

		request.setHeader(header);
		request.setBody(body);
		logger.info("Substituting info:QueryPay BatchSeqID " + serialNumber + " is ready. Start to send!");
		String url1 = getEBServiceURL(ctx);
		java.net.URL endpoint = new java.net.URL(url1);
		EBServiceServiceLocator locator = new EBServiceServiceLocator();
		EBService service = locator.getEBService(endpoint);
		// 返回值
		QueryPayResponse response = service.queryPay(request);
		// 返回异常
		EBException exception = response.getException();
		PayBody responsebody = response.getBody();
		EBHeader responseheader = response.getHeader();
		if (exception == null) {
			logger.info("Substituting info:QueryPay BatchSeqID " + serialNumber + " send success!");
			boolean flag = false;
			// exception为null时，表示银企中间件正常响应，请解析body
			PaymentDetail[] reDetails = responsebody.getDetails();
			String[][] entrys_param = new String[reDetails.length][6];
			ISubstitutingEntry coll = SubstitutingEntryFactory.getLocalInstance(ctx);
			for (int h = 0; h < reDetails.length; h++) {
				PaymentDetail detail = reDetails[h];
				// 业务系统用于标识一笔支付的唯一ID，不能重复
				entrys_param[h][0] = detail.getDetailSeqID();
				SubstitutingEntryInfo subentry = coll.getSubstitutingEntryInfo("where SERIALNUMBER='" + entrys_param[h][0] + "'");
				if (subentry.getBankStatus().equals(BankPayingBillStateEnum.TS) || subentry.getBankStatus().equals(BankPayingBillStateEnum.TF)) {
					continue;
				}
				entrys_param[h][1] = detail.getAmount();
				// EB_PROCESSING:银企中间件处理中;EB_TRANSMIT_FAIL:银企中间件转发失败;
				// BANK_PROCESSING:银行处理中 ;
				// BANK_SUCCESS:银行交易成功;BANK_FAIL:银行交易失败;BANK_EXCEPTION:银行交易异常
				entrys_param[h][2] = detail.getEbStatus();
				// 银企中间件对支付结果的描述
				entrys_param[h][3] = detail.getEbStatusMsg();
				// 银行提供的支付结果的状态码
				entrys_param[h][4] = detail.getBankStatus();
				// 银行提供的支付结果的描述信息
				entrys_param[h][5] = detail.getBankStatusMsg();
				// 更新主表实发金额,实发笔数
				// 更新分录银行状态,银行返回信息,是否成功
				BankPayingBillStateEnum state = null;
				boolean isSuccess = false;
				// 扣款状态
				if ("".equals(entrys_param[h][2])) {
					// 批扣已发起
					state = BankPayingBillStateEnum.DE;
				} else if ("EB_PROCESSING".equals(entrys_param[h][2])) {
					// 准备提交
					state = BankPayingBillStateEnum.OS;
				} else if ("BANK_PROCESSING".equals(entrys_param[h][2])) {
					// 提交成功
					state = BankPayingBillStateEnum.OS;
				} else if ("BANK_SUCCESS".equals(entrys_param[h][2])) {
					// 交易成功
					state = BankPayingBillStateEnum.TS;
					isSuccess = true;
				} else if ("BANK_FAIL".equals(entrys_param[h][2])) {
					// 交易失败
					state = BankPayingBillStateEnum.TF;
				} else if ("BANK_EXCEPTION".equals(entrys_param[h][2])) {
					// 交易未确认
					state = BankPayingBillStateEnum.NC;
				} else if ("EB_TRANSMIT_FAIL".equals(entrys_param[h][2])) {
					// 提交失败
					state = BankPayingBillStateEnum.OF;
				}
				Connection conn = null;
				PreparedStatement pstmt = null;
				try {
					conn = getConnection(ctx);
					// 更新分录银行状态和银行返回信息，并且更新是否成功字段
					String sql = "Update CT_YQ_SubstitutingEntry set CFBankStatus = ?,CFBankReturnInfo = ?,CFIsSucceed = ? where CFSERIALNUMBER  = ? ";
					pstmt = conn.prepareStatement(sql);
					pstmt.setInt(1, state.getValue());
					pstmt.setString(2, entrys_param[h][3] + entrys_param[h][4] + entrys_param[h][5]);
					pstmt.setBoolean(3, isSuccess);
					pstmt.setString(4, entrys_param[h][0]);
					pstmt.executeUpdate();
				} catch (SQLException e) {
					throw new BEException(BEException.WRITESTATEFAILURE);
				} finally {
					SQLUtils.cleanup(null, pstmt, conn);
				}
			}
			// 主要是为跨行调用接口后，重新加载实体，因为实体中分录的状态，和银行返回信息，和流水号已经保存
			EntityViewInfo view = filterViewToAll(bill.getId().toString());
			SubstitutingInfo info = isub.getSubstitutingCollection(view).get(0);
			// 更新代发单实发金额和实发总数，并更新是否成功字段
			reverseSourceBill(ctx, info);
			subhelp.LogForAuxiliaryFunction(ctx, info, InterfaceTypeEnum.BACKMSG, null, auxiliaryFunctions, computerIP, computerName);
			// responsebody.getBatchSeqID();//报账号
			// responsebody.getTotalCount();//总笔数
			// responsebody.getTotalAmount();//总金额
			// responsebody.getVerifyField();//校验字段
		} else if (responsebody == null) {
			logger.info("Substituting info:QueryPay BatchSeqID " + serialNumber + " send exception: " + exception.getMessage() + " ,and the time that happens is "
					+ exception.getTime());
		}
		if (exception != null) {
			throw new BEException(BEException.COMMON, new String[] { exception.getMessage() });
		}
	}

	/**
	 * 取批扣银企平台地址
	 * 
	 * @param ctx
	 * @return String
	 * @throws BEException
	 */
	private String getEBServiceURL(Context ctx) throws BEException {
		 String url = "http://192.168.17.186:5289/services/EBService";
		try {
			ParameterConfigInfo pcInfo = ParameterConfigFactory.getLocalInstance(ctx).getParameterConfigInfo(" where number ='" + ConstantValueUtil.EBSERVICE703_URL + "'");
			if (pcInfo != null && pcInfo.getValue() != null) {
				url = pcInfo.getValue();
			}
		} catch (Exception e) {
			throw new BEException(BEException.COMMON, new String[] { "获取银企平台地址出错!" });
		} 
		return url;
	}

	/**
	 * //此方法2012-12-5日作废,原因:由于此方法提交银企互联2000条数据需要一个小时左右,客户无法接受,所以,以一下方法都作废
	 * 描述：描述：提交银企互联 作者：mmw 创建日期：2012-10-27-下午01:47:37
	 * 
	 * @see com.kingdee.eas.custom.yq.df.app.AbstractSubstitutingControllerBean#_commitToBE(com.kingdee.bos.Context,
	 *      java.util.Set)
	 * @param ctx
	 * @param IdSet单据id集合
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected void _commitToBE(Context ctx, Set IdSet) throws BOSException, EASBizException {
		long s1 = System.currentTimeMillis();
		if (IdSet.size() > 1)
			throw new BEException(BEException.NOTALLOWBATCHSUBMIT);
		Iterator iterator = IdSet.iterator();
		// 检查银企网关
		FmBeHelper.checkWebService(ctx);
		// 校验科目和或账号是否有效,
		checkIdIsValid(ctx, IdSet);

		// 初始化代发单主表接口
		ISubstituting = SubstitutingFactory.getLocalInstance(ctx);

		// 修改代发单状态,提交银企时间,是否提交银企
		reverseSaveForSubstituting(ctx, IdSet);
		// 查出必要的数据的条件
		EntityViewInfo view = filterViewToAll(IdSet);

		// 初始化代发单分录接口
		ISubstitutingEntry = SubstitutingEntryFactory.getLocalInstance(ctx);
		// 初始化银行接口
		Ibebank = BEBankFactory.getLocalInstance(ctx);
		// 初始化公司id
		companyId = ContextHelperFactory.getLocalInstance(ctx).getCurrentCompany().getId().toString();
		// 初始化当前公司
		currentCompany = ContextHelperFactory.getLocalInstance(ctx).getCurrentCompany();
		// 初始化银企日志接口
		banklog = BankLogFactory.getLocalInstance(ctx);
		// 初始化日志功能接口
		bankLogFacade = BankLogFacadeFactory.getLocalInstance(ctx);
		// 代发单辅助功能接口
		auxiliaryFunction = AuxiliaryFunctionFactory.getLocalInstance(ctx);

		SubstitutingCollection coll = ISubstituting.getSubstitutingCollection(view);
		SubHelp subhelp = new SubHelp();
		long s2 = System.currentTimeMillis();
		logger.info("----------------------检测时间------------------用时间为:" + ((s2 - s1) / 10000) + "秒");
		try {
			long s3 = System.currentTimeMillis();
			for (int i = 0; i < coll.size(); i++) {
				SubstitutingInfo info = coll.get(i);
				// 初始化币别
				BOSUuid id = info.getCurrency().getId();
				currencyInfo = CurrencyFactory.getLocalInstance(ctx).getCurrencyInfo(new ObjectUuidPK(id));
				// 初始化用户id
				userId = ContextHelperFactory.getLocalInstance(ctx).getCurrentUser().getId().toString();
				if (info != null) {
					// 封装付款信息
					BankAcnt payBankAcnt = createAgentPayBankAcnt(ctx, info.getPayBankNumber());
					// 工资同行-亲情1+1同行---调用工资批量支付接口,即系统标准的代发单接口
					// 工资跨行-亲情1+1跨行-代收货款---调用普通对公对私接口,即系统标准的付款单接口
					String feetypeNumber = info.getFeeType().getNumber();
					if (feetypeNumber.equals(ConstantValueUtil.WAGES) || feetypeNumber.equals(ConstantValueUtil.KINGSHIPBILL)) {
						// 工资同行-亲情1+1同行
						packSubmitAgentPayment(ctx, info, payBankAcnt);
					} else if (feetypeNumber.equals(ConstantValueUtil.WAGESN) || feetypeNumber.equals(ConstantValueUtil.KINGSHIPBILLN)
							|| feetypeNumber.equals(ConstantValueUtil.REMITREFUNDBILL)) {
						// 工资跨行-亲情1+1跨行-代收货款
						submitPayment(ctx, info, payBankAcnt);
					}
					long s4 = System.currentTimeMillis();
					logger.info("----------------------提交银企互联付款完成------------------用时间为:" + ((s4 - s3) / 1000) + "秒");
					long s5 = System.currentTimeMillis();
					// 主要是为跨行调用接口后，重新加载实体，因为实体中分录的状态，和银行返回信息，和流水号已经保存
					info = ISubstituting.getSubstitutingInfo(new ObjectUuidPK(info.getId().toString()));
					// 更新代发单实发金额和实发总数，并更新是否成功字段
					reverseSourceBill(ctx, info);
					long s6 = System.currentTimeMillis();
					logger.info("----------------------本地数据更新完毕,更新数据有代发单实发金额和实发总数，" + "并更新是否成功字段------------------用时间为:" + ((s6 - s5) / 1000) + "秒");
				}
			}
		} catch (BEException ex) {
			logger.error("summit to ebGateWay failure! beexception message is:", ex);
			// 提交银企失败的回滚
			reverseSaveForAgentPayBill(ctx, IdSet);
			throw ex;
		}
		// 同步代发单付款状态
		// long s7 = System.currentTimeMillis();
		// syncBankAgentPayStateByBill(ctx, FMHelper.set2List(IdSet));
		// long s8 = System.currentTimeMillis();
		//logger.info("----------------------按单据同步状态完毕------------------用时间为:"+(
		// s8-s7)/1000+"秒");
		// 登银行日记账
		long s9 = System.currentTimeMillis();
		subhelp.bookBatchSet(ctx, IdSet);
		long s10 = System.currentTimeMillis();
		logger.info("----------------------本地数据登银行日记状态完毕------------------用时间为:" + ((s10 - s9) / 1000) + "秒");
		logger.info("----------------------全部数据处理完毕------------------用时间为:" + ((s10 - s1) / 1000) + "秒");
	}

	/**
	 * 描述：工资,亲情1+1同行批量付款 作者：mmw 创建日期：2012-11-8-上午08:42:58
	 * 
	 * @param ctx
	 * @param info
	 * @param payBankAcnt
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void packSubmitAgentPayment(Context ctx, SubstitutingInfo info, BankAcnt payBankAcnt) throws EASBizException, BOSException {
		SubstitutingEntryCollection coll = new SubstitutingEntryCollection();
		SelectorItemCollection sele = getSelectorForBe();
		List list = new ArrayList();
		coll = info.getEntrys();
		// 提交银企的条数
		index = 0;
		try {
			for (int i = 0; i < coll.size(); i++) {
				SubstitutingEntryInfo entryinfo = coll.get(i);
				BankPayingBillStateEnum state = entryinfo.getBankStatus();
				// 如果分录状态不为空,则表明这条分录数据已经提交银企,不管状态失败或成功,不允许重复提交银企付款
				if (state != null && !state.equals("") && state != BankPayingBillStateEnum.DE) {
					index++;
					continue;
				}
				coll.add(entryinfo);
				list.add(entryinfo);
			}
			// 分录总共条数

			int count = list.size();
			int size = 0;
			BankBatchSalaryService bankBatchSalaryService = new BankBatchSalaryService(ctx);
			try {
				// 返回的值，即为提交银企平台所允许提交条数的最大值
				size = bankBatchSalaryService.getSubmitSalaryPaymentPageSize(bankBatchSalaryService.createCaller(), payBankAcnt);
			} catch (Exception e) {
				logger.error("summit to ebGateWay failure! exception message is:", e);
				throw new BEException(BEException.COMMON, new String[] { "获取银行账号的最大提交笔数失败！" + e.getMessage() });
			}
			// 除以size的整倍数
			int num1 = count / size;
			// 除以size的余数
			int num2 = count % size;
			// 标示num1大于零
			if (count > size) {
				// 将count分批次以size为单位数量提交银企
				for (int i = 0; i < num1; i++) {
					coll = new SubstitutingEntryCollection();
					for (int j = i * size; j < size * (i + 1); j++) {
						coll.add((SubstitutingEntryInfo) list.get(j));
					}
					// 调用系统代发单接口方法
					// privateBatchSubmit(ctx,coll,info,payBankAcnt,index);
					submitAgentPayment(ctx, info, coll, payBankAcnt);
				}
				// 若余数不为零,则表示除以size有余数,即把剩下的数量单子在此提交
				if (num2 != 0) {
					coll = new SubstitutingEntryCollection();
					for (int i = size * num1; i < count; i++) {
						coll.add((SubstitutingEntryInfo) list.get(i));
					}
					// 调用系统代发单接口方法
					// privateBatchSubmit(ctx,coll,info,payBankAcnt,index);
					submitAgentPayment(ctx, info, coll, payBankAcnt);
				}
			} else {
				// 调用系统代发单接口方法
				// privateBatchSubmit(ctx,coll,info,payBankAcnt,index);
				submitAgentPayment(ctx, info, coll, payBankAcnt);
			}
		} catch (BEException e) {
			// 失败后全部反写
			logger.error("summit to ebGateWay failure! exception message is:", e);
			throw new BEException(BEException.SUMMITFAILURE, new Object[] { e.getMessage() });
		}/*
		 * catch(Exception e){ // 反写交易不明确状态,已经在submit方法中写了 logger.error(e); }
		 */
	}

	/**
	 * 描述：调用付款单接口方法，来提交银企互联 作者：mmw 创建日期：2012-10-23-下午01:52:22
	 * 
	 * @param ctx
	 * @param payBankAcnt
	 * @param info
	 *            ，代发单实体
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void submitPayment(Context ctx, SubstitutingInfo info, BankAcnt payBankAcnt) throws BOSException, EASBizException {
		Set noSet = null;
		Map personMap = null;
		Map noPersonMap = null;
		StringBuffer errStr = new StringBuffer();
		CompanyOrgUnitInfo companyInfo = CompanyOrgUnitFactory.getLocalInstance(ctx).getCompanyOrgUnitInfo(new ObjectUuidPK(info.getCompany().getId()));
		// 根据参数TM018得出系统参数值是否为提交银企节点,若返回结果为0或空都可以通过
		String strValue = ContextHelperFactory.getLocalInstance(ctx).getStringParam("TM018", new ObjectUuidPK(companyInfo.getId()));
		Set validSet = entryValidSet(info);
		if (strValue == null || "0".equals(strValue)) {
			// 取出对私对公的map集合
			Map idMap = divisionPayBillType(ctx, info);
			noPersonMap = (Map) idMap.get("noPersonPay");
			noSet = noPersonMap.keySet();
			personMap = (Map) idMap.get("personPay");
		} else {
			noSet = validSet;
		}
		// 记录已经提交银企分录的条数
		index = 0;
		// 若对公则会进入循环
		for (Iterator iterator = noSet.iterator(); iterator.hasNext();) {
			String id = (String) iterator.next();
			// 对公提交银企互联
			commitToBeAll(ctx, id, strValue, info, payBankAcnt);
			index++;
		}

		// 若对私则进入循环
		if (personMap != null) {
			Set bankKey = personMap.keySet();
			for (Iterator iterator = bankKey.iterator(); iterator.hasNext();) {
				// 获得付款账号信息
				AccountBankInfo key = (AccountBankInfo) iterator.next();
				List payList = (List) personMap.get(key);
				// 对私调用银企互联
				payPrivateToBE(ctx, payList, info, payBankAcnt);
			}
		}
	}

	/**
	 * 描述：代发单跨行，对私付款调用接口 作者：mmw 创建日期：2012-10-23-下午02:05:14
	 * 
	 * @param ctx
	 * @param payList
	 *            代发单分录id
	 * @param accountBank
	 *            银行账号
	 * @param info
	 *            代发单实体
	 * @param payBankAcnt
	 * @param index
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected void payPrivateToBE(Context ctx, List payList, SubstitutingInfo info, BankAcnt payBankAcnt) throws BOSException, EASBizException {
		// 付款单与银行付款单的映射关系
		Map casPayToBankPay = new HashMap();
		SubstitutingEntryCollection coll = new SubstitutingEntryCollection();
		SelectorItemCollection sele = getSelectorForBe();
		List list = new ArrayList();
		try {
			for (int i = 0; i < payList.size(); i++) {
				SubstitutingEntryInfo entryinfo = ISubstitutingEntry.getSubstitutingEntryInfo(new ObjectUuidPK(((SubstitutingEntryInfo) payList.get(i)).getId().toString()), sele);
				BankPayingBillStateEnum state = entryinfo.getBankStatus();
				// 如果分录状态不为空,则表明这条分录数据已经提交银企,不管状态失败或成功,不允许重复提交银企付款
				if (state != null && !state.equals("") && state != BankPayingBillStateEnum.DE) {
					index++;
					continue;
				}
				coll.add(entryinfo);
				list.add(entryinfo);
			}
			// 分录总共条数
			int count = list.size();
			BankPrivateService bankPrivateService = new BankPrivateService(ctx);
			int size = 0;
			try {
				size = bankPrivateService.getSubmitFinancePaymentPageSize(createCaller(), payBankAcnt);
			} catch (Exception err) {
				logger.error("summit to ebGateWay failure! exception message is:", err);
				throw new BEException(BEException.SUMMITFAILURE, new Object[] { err.getMessage() });
			}
			// 除以size的整倍数
			int num1 = count / size;
			// 除以size的余数
			int num2 = count % size;
			// 标示num1大于零
			if (count > size) {
				// 将count分批次以size为单位数量提交银企
				for (int i = 0; i < num1; i++) {
					coll = new SubstitutingEntryCollection();
					for (int j = i * size; j < size * (i + 1); j++) {
						coll.add((SubstitutingEntryInfo) list.get(j));
					}
					// 调用对私付款方法
					privateBatchSubmit(ctx, coll, info, payBankAcnt);
				}
				// 若余数不为零,则表示除以size有余数,即把剩下的数量单子在此提交
				if (num2 != 0) {
					coll = new SubstitutingEntryCollection();
					for (int i = size * num1; i < count; i++) {
						coll.add((SubstitutingEntryInfo) list.get(i));
					}
					// 调用对私付款方法
					privateBatchSubmit(ctx, coll, info, payBankAcnt);
				}
			} else {
				// 调用对私付款方法
				privateBatchSubmit(ctx, coll, info, payBankAcnt);
			}
		} catch (BEException e) {
			// 失败后全部反写
			logger.error("summit to ebGateWay failure! exception message is:", e);
			throw new BEException(BEException.SUMMITFAILURE, new Object[] { e.getMessage() });
		}/*
		 * catch(Exception e){ // 反写交易不明确状态,已经在submit方法中写了 logger.error(e); }
		 */
	}

	/**
	 * 描述：提交对私付款单 作者：mmw 创建日期：2012-10-23-下午02:06:20
	 * 
	 * @param ctx
	 * @param paymentBillColl代发单分录数据集合
	 * @param info代发单实体
	 * @param payBankAcnt
	 *            付款账号的封装参数
	 * @param index
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected void privateBatchSubmit(Context ctx, IObjectCollection paymentBillColl, SubstitutingInfo info, BankAcnt payBankAcnt) throws BOSException, EASBizException {
		if (paymentBillColl == null || paymentBillColl.size() == 0) {
			return;
		}
		PaymentInfo[] parsePaymentInfo = null;
		PaymentInfo[] resultPaymentInfo = null;
		FmBeHelper fmBeHelper = new FmBeHelper();
		SubstitutingEntryInfo entryinfo = new SubstitutingEntryInfo();
		IObjectPK bankLogPk = null;
		SubHelp subhelp = new SubHelp();
		int type = 0;
		FmBeHelper.checkWebService(ctx);
		// 写入日志:开始提交
		logger.info("begin to submit Substituting");
		// 检查
		BankServiceUtil bankServiceUtil = new BankServiceUtil(ctx);
		try {
			parsePaymentInfo = new PaymentInfo[paymentBillColl.size()];
			// 对传过来的分录集合，进行循环调用
			for (int i = 0, size = paymentBillColl.size(); i < size; i++) {
				entryinfo = (SubstitutingEntryInfo) paymentBillColl.getObject(i);
				// 封装付款和收款账号信息
				PaymentInfo PaymentInfo = parsePaymentInfo(ctx, info, entryinfo, payBankAcnt);
				parsePaymentInfo[i] = PaymentInfo;
				// 生产流水号
				String serialNumbers[] = null;
				// 调用银行提供生成流水号的接口
				serialNumbers = bankServiceUtil.getSerialNumber(payBankAcnt, true, 1);
				if (serialNumbers != null && serialNumbers.length == 1) {
					parsePaymentInfo[i].setPackageID(serialNumbers[0]);
					entryinfo.setSerialNumber(serialNumbers[0]);
					ISubstitutingEntry.update(new ObjectUuidPK(entryinfo.getId().toString()), entryinfo);
				}
				// 调用银行提供的校验数据的接口，若异常，则将错误信息传到界面
				PaymentCheckResult rst = bankServiceUtil.checkPayment(PaymentInfo);
				if (rst != null && rst.getAllResult() != null && rst.getAllResult().length > 0) {
					StringBuffer sb = FmBeHelper.getRstMsg(rst);
					if (sb != null && sb.length() > 0) {
						// 若有返回信息，则表明有错误数据，直接往界面报出错误
						throw new BEException(BEException.VERIFYBANKPAYMENT, new Object[] { sb.toString() });
					}
				}
				// 登银企日志
				bankLogPk = buildPrivatePaySend(ctx, parsePaymentInfo, entryinfo, info);
			}
			BankPrivateService bankPrivateService = new BankPrivateService(ctx);

			// 提交银企互联
			resultPaymentInfo = bankPrivateService.submitFinancePayment(createCaller(), parsePaymentInfo);
			type = 1;
			// 提交银企互联之后，更新对应的银企日志
			bankLogPk = bankLogFacade.buildPrivatePayReceive(bankLogPk, resultPaymentInfo);
			// 最后 对每笔返回的付款单进行状态处理
			for (int i = 0; i < paymentBillColl.size(); i++) {
				index++;
				SubstitutingEntryInfo substitutingEntry = (SubstitutingEntryInfo) paymentBillColl.getObject(i);
				PaymentInfo paymentInfo = resultPaymentInfo[i];
				// 读取银行返回状态
				BankPayingBillStateEnum state = FmBeHelper.transferState(paymentInfo.getState());
				String returnMsg = "";
				if (paymentInfo.getResponse() != null) {
					// 读取银行返回信息
					returnMsg = paymentInfo.getResponse().getResponseMessage();
				}
				// 修改状态
				reverseBillState(ctx, state, returnMsg, substitutingEntry, resultPaymentInfo[i].getPackageID());
				// 提交银企互联成功时记录在代发单辅助功能中
				subhelp.LogForAuxiliaryFunction(ctx, info, InterfaceTypeEnum.SUBMIT, entryinfo, auxiliaryFunction, "", "");
			}

		} catch (BankServiceException e) {
			// 明确失败 ,删除生成的银行付款单,反写业务单据为未提交银企互联状态
			logger.error("summit to ebGateWay failure! exception message is:", e);
			bankLogPk = bankLogFacade.buildException(bankLogPk, e, type);
			throw new BEException(BEException.SUMMITFAILURE, new Object[] { "已经提交银企条数为:【" + index + "】！未提交银企条数为:【" + (info.getEntrys().size() - index) + "】！在分录明细表编号为：【"
					+ entryinfo.getDetailNumber() + "】时错误！" + e.getMessage() });
		} catch (BEException e) {// other exception is submit success;
			bankLogPk = bankLogFacade.buildException(bankLogPk, e, type);
			// 明确失败 ,反写业务单据为未提交银企互联状态
			throw new BEException(BEException.COMMON, new Object[] { "已经提交银企条数为:【" + index + "】！未提交银企条数为:【" + (info.getEntrys().size() - index) + "】！在分录明细表编号为：【"
					+ entryinfo.getDetailNumber() + "】时错误！" + e.getMessage() });
		} catch (Exception err) {// other exception is submit success;
			// 防止反写抛出异常导致生成的银行付款单和付款单回滚，
			// 此时银行付款单的状态：如果是反写前失败则状态提交成功，如果是反写后则状态为交易未确认
			err.printStackTrace();
			logger.error(err);
			try {
				// 记录银企日志
				bankLogPk = bankLogFacade.buildException(bankLogPk, err, type);
				// 反写交易不明确状态
				if (!FMHelper.isEmpty(parsePaymentInfo)) {
					for (int i = 0; i < parsePaymentInfo.length; i++) {
						index++;
						PaymentInfo paymentInfo = parsePaymentInfo[i];
						String returnMsg = FmBeHelper.getErrMsg(err);
						BankPayingBillStateEnum state = BankPayingBillStateEnum.NC;
						// 修改状态
						reverseBillState(ctx, state, returnMsg, entryinfo, paymentInfo.getPackageID());
						// 提交银企互联异常时记录在代发单辅助功能中
						subhelp.LogForAuxiliaryFunction(ctx, info, InterfaceTypeEnum.SUBMIT, entryinfo, auxiliaryFunction, "", "");
					}
				}
			} catch (Exception err2) {
				err2.printStackTrace();
			}
		}
	}

	/**
	 * 描述:代发单跨行,提交对私银企日志
	 * 
	 * @param ctx
	 * @param paymentInfos
	 *            提交银企互联时传的参数
	 * @param entryinfo
	 *            分录实体
	 * @param subinfo
	 *            代发单实体
	 * @return 返回银企日志id
	 * @throws BOSException
	 */
	protected IObjectPK buildPrivatePaySend(Context ctx, PaymentInfo[] paymentInfos, SubstitutingEntryInfo entryinfo, SubstitutingInfo subinfo) throws BOSException {
		IObjectPK pk = null;
		try {
			// 实例银企日志
			BankLogInfo info = new BankLogInfo();
			if (FMHelper.hasNumber(ctx, info, companyId))
				info.setNumber(FMHelper.getNumberSilent(ctx, info, companyId));
			info.setCompany(currentCompany);
			// 时间
			info.setTime(Calendar.getInstance().getTime());
			// 业务日期
			info.setBizDate(subinfo.getBizDate());
			info.setBankLogType(BankLogTypeEnum.privatePay);
			// 收款账号信息
			info.setPayAcnt(getPrivatePayAcnt(subinfo));
			// 收款账号
			info.setPayeeAcnt(getPrivatePayeeAcnt(subinfo, entryinfo));
			// 代发单的账号信息包装实体
			BankLogPrivatePaySendInfo bankLogPrivatePaySend = new BankLogPrivatePaySendInfo();
			bankLogPrivatePaySend.setPaymentInfos(paymentInfos);
			bankLogPrivatePaySend.setSubstitutingEntryinfo(entryinfo);
			bankLogPrivatePaySend.setSubstitutinginfo(subinfo);
			info.setSendInfo(getSerialValue(bankLogPrivatePaySend));
			// 保存银企日志返回主键id
			pk = banklog.addnew(info);
		} catch (Exception e) {
			if (logger.isInfoEnabled())
				logger.info(e.getMessage());
		}
		return pk;
	}

	/**
	 * 描述：对公提交银企的包装方法 作者：mmw 创建日期：2012-10-23-下午02:22:12
	 * 
	 * @param ctx
	 * @param bankPayingbillId
	 *            代发单分录id
	 * @param strValue
	 * @param payBankAcnt
	 *            付款账号封装参数
	 * @param index
	 *            已经提交到了多少条数据
	 * @param info代发单实体
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected void commitToBeAll(Context ctx, String bankPayingbillId, String strValue, SubstitutingInfo info, BankAcnt payBankAcnt) throws BOSException, EASBizException {
		// 开始真正提交银企互联的事务
		SubstitutingEntryCollection coll = new SubstitutingEntryCollection();
		SelectorItemCollection sele = getSelectorForBe();
		SubstitutingEntryInfo entryInfo = ISubstitutingEntry.getSubstitutingEntryInfo(new ObjectUuidPK(bankPayingbillId), sele);
		BankPayingBillStateEnum state = entryInfo.getBankStatus();
		// 如果分录状态不为空,则表明这条分录数据已经提交银企,不管状态失败或成功,不允许重复提交银企付款
		if (state != null && !state.equals("") && state != BankPayingBillStateEnum.DE)
			return;
		coll.add(entryInfo);
		if (entryInfo != null) {
			// 如果提交节点是业务单据的话
			if (strValue == null || "0".equals(strValue)) {
				try {
					// 提交银企方法
					submit(ctx, coll, info, payBankAcnt);
				} catch (BEException e) {
					logger.error("summit to ebGateWay failure! exception message is:", e);
					throw new BEException(BEException.SUMMITFAILURE, new Object[] { "已经提交银企条数为:【" + index + "】！未提交银企条数为:【" + (info.getEntrys().size() - index) + "】！在分录明细表编号为：【"
							+ entryInfo.getDetailNumber() + "】时错误！" + e.getMessage() });
				} catch (Exception err) {// other exception is submit
					// success;
					// 反写交易不明确状态,已经在submit方法中写了
					logger.error(err);
				}
			}
		}
	}

	/**
	 * 描述：提交银行付款单到银企网关 抛出异常BEException，代表提交银企网关失败 作者：mmw
	 * 创建日期：2012-10-23-下午02:24:12
	 * 
	 * @param ctx
	 * @param paymentBillColl
	 *            代发单分录集合
	 * @param info
	 *            代发单实体
	 * @param payBankAcnt
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected void submit(Context ctx, IObjectCollection paymentBillColl, SubstitutingInfo info, BankAcnt payBankAcnt) throws BOSException, EASBizException {
		if (paymentBillColl == null || paymentBillColl.size() == 0) {
			return;
		}
		FmBeHelper fmBeHelper = new FmBeHelper();
		FmBeHelper.checkWebService(ctx);
		// 写入日志:开始提交
		logger.info("begin to submit Sutstituting");
		SubstitutingEntryInfo entryInfo = null;
		SubHelp subhelp = new SubHelp();
		int type = 0;
		IObjectPK bankLogPk = null;
		BankServiceUtil bankServiceUtil = new BankServiceUtil(ctx);
		// 生产流水号
		String serialNumbers[];
		entryInfo = (SubstitutingEntryInfo) paymentBillColl.getObject(0);
		try {
			serialNumbers = bankServiceUtil.getSerialNumber(payBankAcnt, true, 1);
			entryInfo.setSerialNumber(serialNumbers[0]);
			ISubstitutingEntry.update(new ObjectUuidPK(entryInfo.getId().toString()), entryInfo);
		} catch (Exception e1) {
			throw new BEException(BEException.COMMON, new Object[] { "获取流水号失败！提示：这与付款账号有关。" });
		}
		// 分录集合，其实大小是1
		for (int i = 0, size = paymentBillColl.size(); i < size; i++) {
			type = 0;
			entryInfo = (SubstitutingEntryInfo) paymentBillColl.getObject(i);
			try {
				String returnMsg = "";
				PaymentCheckResult rst = null;
				BankPayingBillStateEnum state = null;
				// if
				// (FMHelper.isEmpty(entryInfo.getParentAccount())){//付款单的母账号，
				// 这里是代发单，所以没有此属性
				// 封装代发单，并校验数据的正确性
				PaymentInfo parsePaymentInfo = parsePaymentInfo(ctx, info, entryInfo, payBankAcnt);

				if (serialNumbers != null && serialNumbers.length == 1) {
					parsePaymentInfo.setPackageID(serialNumbers[0]);
				}
				rst = bankServiceUtil.checkPayment(parsePaymentInfo);
				if (rst != null && rst.getAllResult() != null && rst.getAllResult().length > 0) {
					StringBuffer sb = FmBeHelper.getRstMsg(rst);
					if (sb != null && sb.length() > 0) {
						// 若调用的银行数据校验接口，返回的参数有值，则表明有错误，直接往界面抛出错误信息
						throw new BEException(BEException.VERIFYBANKPAYMENT, new Object[] { sb.toString() });
					}
				}
				// 提交银企互联时记录银企日志
				bankLogPk = buildPaySend(ctx, parsePaymentInfo, info.getPayBankNumber(), entryInfo.getPayeeNumber(), entryInfo, info);
				// 提交银企互联主要代码
				PaymentInfo paymentInfo = bankServiceUtil.submitPayment(createCaller(), parsePaymentInfo);
				type = 1;
				// 提交银企互联时更新银企日志
				bankLogPk = bankLogFacade.buildPayReceive(bankLogPk, paymentInfo);
				// 获取银行返回状态及信息
				state = FmBeHelper.transferState(paymentInfo.getState());
				if (paymentInfo.getResponse() != null) {
					returnMsg = paymentInfo.getResponse().getResponseMessage();
				}
				// 反写状态
				reverseBillState(ctx, state, returnMsg, entryInfo, serialNumbers[0]);
				// 提交银企互联成功时记录在代发单辅助功能中
				subhelp.LogForAuxiliaryFunction(ctx, info, InterfaceTypeEnum.SUBMIT, entryInfo, auxiliaryFunction, "", "");
				// }else{
				// LinkPaymentInfo parsePaymentInfo =
				// fmBeHelper.parseLinkPaymentInfo(ctx, info);
				// BankLinkConfigUtil bankLinkConfigUtil = new
				// BankLinkConfigUtil(ctx);
				// rst =bankLinkConfigUtil.checkLinkPayment(createCaller(),
				// parsePaymentInfo);
				// if (rst != null && rst.getAllResult() != null
				// && rst.getAllResult().length > 0) {
				// StringBuffer sb = FmBeHelper.getRstMsg(rst);
				// if (sb != null && sb.length() > 0) {
				// throw new BEException(BEException.VERIFYBANKPAYMENT,
				// new Object[] { sb.toString() });
				// }
				// }
				// LinkPaymentInfo paymentInfo =
				// bankLinkConfigUtil.submitLinkPayment
				// (createCaller(),parsePaymentInfo);
				// if(debug)
				// {
				// throw new BEException(BEException.COMMITFAILURE);
				// }
				// state = FmBeHelper.transferState(paymentInfo.getState());
				// if (paymentInfo.getResponse() != null) {
				// returnMsg = paymentInfo.getResponse().getResponseMessage();
				// }
				// // 反写状态
				// reverseBillState(ctx,state,
				// paymentInfo.getPackageID(),returnMsg
				// ,info.getId().toString());
				// }

				// // 更新业务单据
				// if (!FMHelper.isEmpty(info.getSourceBillId()))
				// {
				// reverseSourceBillState(ctx, state,
				// returnMsg,info.getSourceBillId().toString()) ;
				// }

			} catch (BankServiceException e) {
				// 明确失败 ,删除生成的银行付款单,反写业务单据为未提交银企互联状态
				logger.error("summit to ebGateWay failure! exception message is:", e);
				bankLogPk = bankLogFacade.buildException(bankLogPk, e, type);
				throw new BEException(BEException.SUMMITFAILURE, new Object[] { e.getMessage() });
			} catch (BEException err) {// other exception is submit success;
				bankLogPk = bankLogFacade.buildException(bankLogPk, err, type);
				// 明确失败 ,删除生成的银行付款单,反写业务单据为未提交银企互联状态
				throw err;
			} catch (Exception err) {// other exception is submit success;
				// 防止反写抛出异常导致生成的银行付款单和付款单回滚，
				// 此时银行付款单的状态：如果是反写前失败则状态提交成功，如果是反写后则状态为交易未确认
				err.printStackTrace();
				logger.error(err);
				try {
					bankLogPk = bankLogFacade.buildException(bankLogPk, err, type);
					// 反写交易不明确状态
					String returnMsg = FmBeHelper.getErrMsg(err);
					BankPayingBillStateEnum state = BankPayingBillStateEnum.NC;
					reverseBillState(ctx, state, returnMsg, entryInfo, serialNumbers[0]);
					// 提交银企互联异常时记录在代发单辅助功能中
					subhelp.LogForAuxiliaryFunction(ctx, info, InterfaceTypeEnum.SUBMIT, entryInfo, auxiliaryFunction, "", "");
				} catch (Exception err2) {
					err2.printStackTrace();
				}
			}
		}
	}

	/**
	 * 描述：封装分录id
	 * 
	 * @param info
	 * @return
	 */
	private Set entryValidSet(SubstitutingInfo info) {
		Set set = new HashSet();
		for (int i = 0; i < info.getEntrys().size(); i++) {
			BOSUuid id = info.getEntrys().get(i).getId();
			if (id != null) {
				String valid = id.toString();
				set.add(id);
			}
		}
		return set;
	}

	/**
	 * 描述：整理代发单分录的对私和对公 作者：mmw 创建日期：2012-10-23-下午02:35:58
	 * 
	 * @param ctx
	 * @param info
	 *            代发单实体
	 * @return 返回对私和对公的集合
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private Map divisionPayBillType(Context ctx, SubstitutingInfo info) throws BOSException, EASBizException {
		Map all = new HashMap();
		// 对公集合
		Map noPersonmao = new HashMap();
		// 对私集合
		Map personmap = new HashMap();
		// 分录集合接口
		SubstitutingEntryCollection coll = info.getEntrys();
		for (int i = 0; i < coll.size(); i++) {
			String id = coll.get(i).getId().toString();
			EntityViewInfo evi = new EntityViewInfo();
			SelectorItemCollection si = evi.getSelector();
			si.add("PayBankNumber.*");
			si.add("PayBankNumber.bank.*");
			si.add("settlementType.*");
			SubstitutingEntryInfo entryInfo = SubstitutingEntryFactory.getLocalInstance(ctx).getSubstitutingEntryInfo(new ObjectUuidPK(id), si);
			// 通过判断结算方式来判断是否对私，若没有，则走对公付款接口
			if (entryInfo.getSettlementType() == null)
				noPersonmao.put(id, info.getNumber());
			else if (entryInfo.getSettlementType().isIsPersonPay()) {
				// 若分录收款账号是对私付款，则将账号信息和分录实体填充到map集合中
				if (personmap.get(info.getPayBankNumber()) != null) {
					List paymentList = (List) personmap.get(info.getPayBankNumber());
					paymentList.add(entryInfo);
					personmap.put(info.getPayBankNumber(), paymentList);
				} else {
					List paymentList = new ArrayList();
					paymentList.add(entryInfo);
					personmap.put(info.getPayBankNumber(), paymentList);
				}
			} else {
				// 对公付款，则在此记录
				noPersonmao.put(id, info.getNumber());
			}
		}

		all.put("personPay", personmap);
		all.put("noPersonPay", noPersonmao);
		return all;
	}

	/**
	 * 描述：查出必要的数据的条件 作者：mmw 创建日期：2012-10-23-下午02:45:33
	 * 
	 * @param IdSet
	 *            代发单id集合
	 * @return
	 */
	private EntityViewInfo filterViewToAll(Set IdSet) {
		SubstitutingCollection collection = new SubstitutingCollection();
		FilterInfo filter = new FilterInfo();
		EntityViewInfo view = new EntityViewInfo();
		filter.getFilterItems().add(new FilterItemInfo("id", new HashSet(IdSet), CompareType.INCLUDE));
		view.setFilter(filter);
		SelectorItemCollection sele = new SelectorItemCollection();
		sele.add("*");
		sele.add("entrys.*");
		sele.add("payBankNumber.*");
		sele.add("feeType.number");
		sele.add("feeType.name");
		sele.add("entrys.payeeArea.number");
		sele.add("entrys.payeeArea.name");
		sele.add("entrys.payeeArea.deptId");
		sele.add("entrys.payeeCity.name");
		sele.add("entrys.PayBankNumber.*");
		sele.add("entrys.PayBankNumber.bank.*");
		sele.add("entrys.settlementType.*");
		view.setSelector(sele);
		return view;
	}

	/**
	 * 描述：提交成功，更新代发单实发金额，实发笔数，分录是否成功 作者：mmw 创建日期：2012-10-23-下午02:46:36
	 * 
	 * @param ctx
	 * @param info
	 *            代发单实体
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void reverseSourceBill(Context ctx, SubstitutingInfo info) throws BOSException, EASBizException {
		BigDecimal totalAmount = FMConstants.ZERO;
		int totalCount = 0;
		SubstitutingEntryCollection entrycoll = info.getEntrys();
		for (int i = 0; i < entrycoll.size(); i++) {
			SubstitutingEntryInfo substitutingEntry = entrycoll.get(i);
			// 交易成功，则改写是否成功字段和主表实发金额和实发笔数
			if (BankPayingBillStateEnum.TS.equals(substitutingEntry.getBankStatus())) {
				totalAmount = totalAmount.add(substitutingEntry.getAmount());
				totalCount++;
			}
		}
		// 更新代发单的实发金额和实发笔数
		info.setFactAmount(totalAmount);
		info.setFactPenNumber(totalCount);
		SelectorItemCollection item = new SelectorItemCollection();
		item.add(new SelectorItemInfo("factAmount"));
		item.add(new SelectorItemInfo("factPenNumber"));
		SubstitutingFactory.getLocalInstance(ctx).updatePartial(info, item);
	}

	/**
	 * 描述：调用普通对公对私接口时所需要传的封装参数
	 * 
	 * @param ctx
	 * @param info
	 *            代发单实体
	 * @param entryInfo
	 *            分录实体
	 * @param payBankAcnt
	 * @return 代发单数据封装实体
	 * @throws BOSException
	 * @throws EASBizException
	 * @throws RemoteException
	 * @throws ServiceException
	 */
	public PaymentInfo parsePaymentInfo(Context ctx, SubstitutingInfo info, SubstitutingEntryInfo entryInfo, BankAcnt payBankAcnt) throws BOSException, EASBizException,
			RemoteException, ServiceException {
		// 收款账户信息的封装实体
		BankAcnt recBankAcnt = createAgentRecBankAcnt(ctx, entryInfo);
		// 实例化提交银企互联时所需的数据参数
		PaymentInfo paymentInfo = new PaymentInfo();
		// 付款账户信息的封装实体
		paymentInfo.setBankAcnt(payBankAcnt);
		paymentInfo.setOppBankAcnt(recBankAcnt);
		// 若分录的流水号不存在，则调用银行接口生成流水号
		if (FMHelper.isEmpty(entryInfo.getSerialNumber())) {
			BankServiceUtil bankServiceUtil = new BankServiceUtil(ctx);
			String serialNumbers[] = bankServiceUtil.getSerialNumber(payBankAcnt, true, 1);
			if (serialNumbers != null && serialNumbers.length == 1)
				paymentInfo.setPackageID(serialNumbers[0]);
		} else {
			paymentInfo.setPackageID(entryInfo.getSerialNumber());
		}
		String currency = getCurrency(ctx, currencyInfo);
		// 币别
		paymentInfo.setCurrency(currency);
		// 金额
		paymentInfo.setAmount(entryInfo.getAmount());
		Timestamp time = new Timestamp(Calendar.getInstance().getTimeInMillis());
		// 期望交易时间
		paymentInfo.setBookingDate(time);
		// 备注
		paymentInfo.setExplanation(info.getUsage());
		// 是否同城
		paymentInfo.setSameCity(entryInfo.getDifPlace().getValue() == 0);
		// 提交银企时间
		paymentInfo.setSubmitDate(Calendar.getInstance().getTime());
		// 提交用户id
		paymentInfo.setSubmiterID(userId);
		// 单据编号
		paymentInfo.setBusinessRefNumber(info.getNumber());
		// 是否加急，这里默认true
		paymentInfo.setUrgent(true);
		// 默认准备提交
		paymentInfo.setState(PaymentState.WILLSUBMIT);
		String recBank = entryInfo.getPayeeBank();
		String item = Ibebank.getBankNo(recBank);
		// 付款账号
		paymentInfo.setBankNumber(item);
		if (entryInfo.getPayeeCountry() == null)
			;
		boolean sameBank = true;
		com.kingdee.eas.fm.be.DifBankEnum difBankEnum = entryInfo.getDifBank();
		if (difBankEnum != null && difBankEnum.getValue() == 1)
			sameBank = false;
		// 是否同行
		paymentInfo.setSameBank(sameBank);
		return paymentInfo;
	}

	/**
	 * 描述：代发单查出数据的字段 作者：mmw 创建日期：2012-10-23-下午02:52:26
	 * 
	 * @return 查出数据相的集合
	 */
	private SelectorItemCollection getSelectorForBe() {
		SelectorItemCollection sele = new SelectorItemCollection();
		sele.add("*");
		sele.add("payeeProvince.*");
		sele.add("payeeCity.*");
		sele.add("payeeArea.*");
		return sele;
	}

	/**
	 * 描述：校验数据是否有效 作者：mmw 创建日期：2012-10-23-下午02:53:58
	 * 
	 * @param ctx
	 * @param idSet
	 *            代发单id集合
	 * @throws EASBizException
	 * @throws BOSException
	 */
	private void checkIdIsValid(Context ctx, Set idSet) throws EASBizException, BOSException {
		FilterInfo filter = new FilterInfo();
		filter.getFilterItems().add(new FilterItemInfo("id", idSet, CompareType.INCLUDE));
		EntityViewInfo evi = new EntityViewInfo();
		evi.setFilter(filter);
		evi.getSelector().add("*");
		evi.getSelector().add("OppAccount.*");
		evi.getSelector().add("company.*");
		evi.getSelector().add("entrys.*");
		evi.getSelector().add("entrys.SettlementType.*");
		evi.getSelector().add("entrys.SettlementType.isPayThroughBE");
		evi.getSelector().add("payBankNumber.bankInterfaceType");
		ISubstituting iSubstituting = SubstitutingFactory.getLocalInstance(ctx);
		SubstitutingCollection coll = iSubstituting.getSubstitutingCollection(evi);
		for (int i = 0, size = coll.size(); i < size; i++) {
			SubstitutingInfo info = coll.get(i);
			// 检查提交数据的最大值
			// checkSubmitEntryTOMaxSize(ctx,info);
			// 校验必要的参数的正确性，若有误，则直接将错误抛到界面弹出
			if (FMHelper.isEmpty(info.getPayBankNumber())) {
				throw new BEException(BEException.COMMON, new Object[] { "代发单未设置付款账号不能提交银企互联！" });
			}
			if (!info.getBillStatus().equals(BillStatusEnum.AUDITED) && FMHelper.isEmpty(info.getPayBankNumber())) {
				throw new BEException(BEException.COMMON, new Object[] { "已审批状态且付款账户不为空的代发单才允许提交银企互联！" });
			}
			if (FMHelper.isEmpty(info.getUsage())) {
				throw new BEException(BEException.COMMON, new Object[] { "代发单未设置用途不能提交银企互联！" });
			}
			ISettlementType settlementType = SettlementTypeFactory.getLocalInstance(ctx);
			SubstitutingEntryCollection Entrycoll = info.getEntrys();
			for (int j = 0; j < Entrycoll.size(); j++) {
				SubstitutingEntryInfo entryinfo = Entrycoll.get(j);
				BOSUuid typeid = entryinfo.getSettlementType().getId();
				SettlementTypeInfo st = settlementType.getSettlementTypeInfo(new ObjectUuidPK(typeid));
				if (st == null) {
					throw new BEException(BEException.COMMON, new Object[] { "代发单分录第" + (j + 1) + "行结算方式为空，不能提交银企！" });
				} else if (!st.isPayThroughBE()) {
					throw new BEException(BEException.COMMON, new Object[] { "结算方式不支持通过银企直连付款，不能提交银企互联！" });
				}
			}
			if (info.getPayAccount() != null) {
				// 检查付款科目是否有效
				checkAcctViewIsValid(ctx, info.getNumber(), info.getCompany(), info.getPayAccount());
			}
			if (info.getOppAccount() != null) {
				// 检查对方科目是否有效
				checkAcctViewIsValid(ctx, info.getNumber(), info.getCompany(), info.getOppAccount());
			}
			if (info.getPayBankNumber().getBankInterfaceType() == null) {
				throw new BEException(BEException.BANKINTERFACE);
			}
		}
	}

	/**
	 * 描述：代发单提交时验证总笔数是否超出银企平台提供的银行要求的笔数
	 * 
	 * @param info
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void checkSubmitEntryTOMaxSize(Context ctx, SubstitutingInfo info) throws EASBizException, BOSException {
		if (info.getPayBankNumber() != null) {
			if (info.getPayBankNumber().getBankInterfaceType() != null) {
				FmBeHelper.checkWebService(ctx);
				BankBatchSalaryService bankBatchSalaryService = new BankBatchSalaryService(ctx);
				BankAcnt acnt = createAgentPayBankAcnt(ctx, info.getPayBankNumber());
				try {
					// 返回的值，即为提交银企平台所允许提交条数的最大值
					int SubmitSize = bankBatchSalaryService.getSubmitSalaryPaymentPageSize(bankBatchSalaryService.createCaller(), acnt);
					if (SubmitSize < info.getEntrys().size()) {
						throw new BEException(BEException.COMMON, new String[] { "代发单提交验证总笔数超出银企平台支持的最大笔数" + SubmitSize + "！" });
					}
				} catch (Exception e) {
					e.printStackTrace();
					throw new BEException(BEException.COMMON, new String[] { "获取银行账号的最大提交笔数失败！" + e.getMessage() });
				}
			}
		}
	}

	/**
	 * 描述:校验科目是否有效
	 * 
	 * @param ctx
	 * @param billNumber
	 * @param company
	 * @param view
	 * @throws BOSException
	 * @throws EASBizException
	 */
	public static void checkAcctViewIsValid(Context ctx, String billNumber, CompanyOrgUnitInfo company, AccountViewInfo view) throws BOSException, EASBizException {
		if (company == null || view == null)
			return;
		// 公司即组织
		ICompanyOrgUnit iCompany = null;
		if (ctx == null)
			iCompany = CompanyOrgUnitFactory.getRemoteInstance();
		else
			iCompany = CompanyOrgUnitFactory.getLocalInstance(ctx);
		if (company.getAccountTable() == null)
			company = iCompany.getCompanyOrgUnitInfo(new ObjectUuidPK(company.getId()));
		IAccountView iAcctView = null;
		if (ctx == null)
			iAcctView = AccountViewFactory.getRemoteInstance();
		else
			iAcctView = AccountViewFactory.getLocalInstance(ctx);
		if (view.getAccountTableID() == null)
			view = iAcctView.getAccountViewInfo(new ObjectUuidPK(view.getId().toString()));
		// 校验账号是否有效
		if (!view.getAccountTableID().getId().equals(company.getAccountTable().getId()))
			throw new BEException(BEException.COMMON, new Object[] { "单据" + billNumber + "的收(付)款科目或对方科目已不是当前公司的科目，不允许修改、提交结算中心、提交银企互联、开票、付款或生成凭证！" });
		else
			return;
	}

	/**
	 * 提交银企失败的回滚逻辑
	 * 
	 * @param ctx
	 * @param idSet
	 *            代发单id集合
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void reverseSaveForAgentPayBill(Context ctx, Set idSet) throws BOSException, EASBizException {
		Iterator iter = idSet.iterator();
		// 主要回滚单据状态,提交银企时间,是否提交银企互联
		SubstitutingInfo info = SubstitutingFactory.getLocalInstance(ctx).getSubstitutingInfo(new ObjectUuidPK((String) iter.next()));
		// 单据状态为已审核
		info.setBillStatus(BillStatuEnum.AUDITOR);
		// 提交银企时间为空
		info.setSubmitBankDate(null);
		// 是否提交银企为false
		info.setIsSubmitBank(false);
		SelectorItemCollection item = new SelectorItemCollection();
		item.add(new SelectorItemInfo("billStatus"));
		item.add(new SelectorItemInfo("submitBankDate"));
		item.add(new SelectorItemInfo("isSubmitBank"));
		SubstitutingFactory.getLocalInstance(ctx).updatePartial(info, item);
	}

	/**
	 * 提交银企前修改代发单状态,提交银企时间,是否提交银企
	 * 
	 * @param ctx
	 * @param idSet代发单集合
	 * @throws BOSException
	 * @throws EASBizException
	 * @throws BOSException
	 * @throws
	 */
	private void reverseSaveForSubstituting(Context ctx, Set idSet) throws EASBizException, BOSException {
		// 出纳标志,idSet其实只有一个值,
		Iterator iter = idSet.iterator();
		SubstitutingInfo info = SubstitutingFactory.getLocalInstance(ctx).getSubstitutingInfo(new ObjectUuidPK((String) iter.next()));
		// 单据状态为已付款
		info.setBillStatus(BillStatuEnum.PAYING);
		// 提交银企时间默认为当前时间
		info.setSubmitBankDate(new Date());
		// 是否提交银企为true
		info.setIsSubmitBank(true);
		SelectorItemCollection item = new SelectorItemCollection();
		item.add(new SelectorItemInfo("billStatus"));
		item.add(new SelectorItemInfo("submitBankDate"));
		item.add(new SelectorItemInfo("isSubmitBank"));
		SubstitutingFactory.getLocalInstance(ctx).updatePartial(info, item);
	}

	/**
	 * 描述：系统代发单接口提交银企互联‘’‘’‘’
	 * 
	 * @param ctx
	 * @param info
	 * @param index
	 * @param payBankAcnt
	 * @param type
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void submitAgentPayment(Context ctx, SubstitutingInfo info, SubstitutingEntryCollection subcoll, BankAcnt payBankAcnt) throws BOSException, EASBizException {
		PaymentInfo paymentInfos[] = new PaymentInfo[subcoll.size()];
		int types = 0;
		IObjectPK bankLogPk = null;
		SubHelp subhelp = new SubHelp();
		SubstitutingEntryInfo entryInfo = new SubstitutingEntryInfo();
		try {
			FmBeHelper fmBeHelper = new FmBeHelper();
			FmBeHelper.checkWebService(ctx);
			// 校验代发单
			for (int i = 0, size = subcoll.size(); i < size; i++) {
				entryInfo = subcoll.get(i);
				PaymentInfo parsePaymentInfo = parseAgentPayInfo(ctx, info, entryInfo, payBankAcnt);

				paymentInfos[i] = parsePaymentInfo;
				BankBatchSalaryService bankBatchSalaryService = new BankBatchSalaryService(ctx);
				// 生成流水号
				String[] serNumber = bankBatchSalaryService.getBatchSalarySerialNumber(bankBatchSalaryService.createCaller(), paymentInfos);
				if (serNumber[i] != null) {
					paymentInfos[i].setPackageID(serNumber[i]);
					SelectorItemCollection item = new SelectorItemCollection();
					item.add(new SelectorItemInfo("serialNumber"));
					entryInfo.setSerialNumber(serNumber[i]);
					ISubstitutingEntry.updatePartial(entryInfo, item);
				}
				PaymentCheckResult rst = bankBatchSalaryService.checkSalaryPayment(bankBatchSalaryService.createCaller(), paymentInfos[i]);
				if (rst != null && rst.getAllResult() != null && rst.getAllResult().length > 0) {
					StringBuffer sb = FmBeHelper.getRstMsg(rst);
					if (sb != null && sb.length() > 0)
						throw new BEException(BEException.VERIFYBANKAGENTPAY, new Object[] { sb.toString() });
				}
			}
			// //更新获取到的流水号信息
			// for(int i=0;i<paymentInfos.length;i++){
			// subcoll.get(i).setSerialNumber(paymentInfos[i].getPackageID());
			// }
			// update(ctx, new ObjectUuidPK(info.getId().toString()), info);
			// 提交银企互联时记录银企日志
			bankLogPk = buildBankAgentPayBillSend(ctx, paymentInfos, info);
			// 提交银企互联主要代码
			BankBatchSalaryService bankBatchSalaryService = new BankBatchSalaryService(ctx);
			paymentInfos = bankBatchSalaryService.submitSalaryPayment(createCaller(), paymentInfos);
			types = 1;
			// 提交银企互联时更新银企日志
			BankLogFacadeFactory.getLocalInstance(ctx).buildBankAgentPayBillReceive(bankLogPk, paymentInfos);
			// 修改状态
			// 最后 对每笔返回的付款单进行状态处理
			for (int i = 0; i < subcoll.size(); i++) {
				index++;
				SubstitutingEntryInfo substitutingEntry = (SubstitutingEntryInfo) subcoll.getObject(i);
				PaymentInfo paymentInfo = paymentInfos[i];
				// 读取银行返回状态
				BankPayingBillStateEnum state = FmBeHelper.transferState(paymentInfo.getState());
				String returnMsg = "";
				if (paymentInfo.getResponse() != null) {
					// 读取银行返回信息
					returnMsg = paymentInfo.getResponse().getResponseMessage();
				}
				// 修改状态,及更新业务流水号
				reverseBillState(ctx, state, returnMsg, substitutingEntry, paymentInfos[i].getPackageID());
				// 提交银企互联成功时记录在代发单辅助功能中
				subhelp.LogForAuxiliaryFunction(ctx, info, InterfaceTypeEnum.SUBMIT, entryInfo, auxiliaryFunction, "", "");
			}
			// reverseBankAgentPayingBill(ctx, info, paymentInfos);在
			// 提交银企互联成功时记录在代发单辅助功能中
			// subhelp.LogForAuxiliaryFunction(ctx, info,
			// InterfaceTypeEnum.SUBMIT);
		} catch (BankServiceException e) {
			BankLogFacadeFactory.getLocalInstance(ctx).buildException(bankLogPk, e, types);
			logger.error("summit to ebGateWay(Sub) failure! exception message is:", e);
			// 明确失败 ,反写业务单据为未提交银企互联状态
			throw new BEException(BEException.SUMMITFAILURE, new Object[] { "已经提交银企条数为:【" + index + "】！未提交银企条数为:【" + (info.getEntrys().size() - index) + "】！在分录明细表编号为：【"
					+ entryInfo.getDetailNumber() + "】时错误！" + e.getMessage() });
		} catch (BEException e) {
			BankLogFacadeFactory.getLocalInstance(ctx).buildException(bankLogPk, e, types);
			throw new BEException(BEException.COMMON, new Object[] { "已经提交银企条数为:【" + index + "】！未提交银企条数为:【" + (info.getEntrys().size() - index) + "】！在分录明细表编号为：【"
					+ entryInfo.getDetailNumber() + "】时错误！" + e.getMessage() });
		} catch (Exception e) {
			BankLogFacadeFactory.getLocalInstance(ctx).buildException(bankLogPk, e, types);
			logger.error("summit to ebGateWay(Sub) failure! exception message is:", e);
			// 对于不明确的异常，一律反写为交易未确认状态，由用户进行同步确认
			for (int i = 0; i < paymentInfos.length; i++) {
				index++;
				PaymentInfo paymentInfo = paymentInfos[i];
				BankPayingBillStateEnum state = BankPayingBillStateEnum.NC;
				String responseMessage = "";
				if (paymentInfos[i].getResponse() != null)
					responseMessage = paymentInfos[i].getResponse().getResponseMessage();
				// reverseBankAgentPayingBill(ctx, info, paymentInfos);
				// 修改状态
				reverseBillState(ctx, state, responseMessage, entryInfo, paymentInfo.getPackageID());
				// 提交银企互联异常时记录在代发单辅助功能中
				subhelp.LogForAuxiliaryFunction(ctx, info, InterfaceTypeEnum.SUBMIT, entryInfo, auxiliaryFunction, "", "");
			}
		}
	}

	/**
	 * 描述：生成银企日志 作者：mmw 创建日期：2012-10-23-下午02:59:08
	 * 
	 * @param ctx
	 * @param paymentInfo提交银企所需的封装参数
	 * @param payAcnt付款账号
	 * @param payeeAcnt
	 * @param substitutingEntryinfo代发单分录
	 * @param substitutinginfo代发单实体
	 * @return返回银企日志的主键id
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected IObjectPK buildPaySend(Context ctx, PaymentInfo paymentInfo, AccountBankInfo payAcnt, String payeeAcnt, SubstitutingEntryInfo substitutingEntryinfo,
			SubstitutingInfo substitutinginfo) throws BOSException, EASBizException {
		IObjectPK pk = null;
		try {
			// 实例化银企日志
			BankLogInfo info = new BankLogInfo();
			if (FMHelper.hasNumber(ctx, info, companyId))
				info.setNumber(FMHelper.getNumberSilent(ctx, info, companyId));
			// 公司
			info.setCompany(currentCompany);
			// 时间
			info.setTime(Calendar.getInstance().getTime());
			// 业务日期
			info.setBizDate(substitutinginfo.getBizDate());
			// 银行日记类型
			info.setBankLogType(BankLogTypeEnum.Pay);
			// 付款账号的名称
			info.setPayAcnt(payAcnt.getName());
			// 付款账号
			info.setPayeeAcnt(payeeAcnt);
			// 封装提交银企数据的实体
			BankLogSubstitutingEntrySendInfo bankLogPaySend = new BankLogSubstitutingEntrySendInfo();
			bankLogPaySend.setPaymentInfo(paymentInfo);
			bankLogPaySend.setBankPayingEntryInfo(substitutingEntryinfo);
			bankLogPaySend.setBankPayinginfo(substitutinginfo);
			info.setSendInfo(getSerialValue(bankLogPaySend));
			// 保存银企日志信息
			pk = banklog.addnew(info);
		} catch (Exception e) {
			if (logger.isInfoEnabled())
				logger.info(e.getMessage());
		}
		return pk;
	}

	/**
	 * 描述：更新银企日记账 作者：mmw 创建日期：2012-10-23-下午03:02:55
	 * 
	 * @param ctx
	 * @param paymentInfos
	 *            代发单封的实体装参数
	 * @param SubstitutingInfo代发单实体
	 * @return返回银企日志主键id
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected IObjectPK buildBankAgentPayBillSend(Context ctx, PaymentInfo paymentInfos[], SubstitutingInfo SubstitutingInfo) throws BOSException, EASBizException {
		IObjectPK pk = null;
		try {
			// 实例化银企日志
			BankLogInfo info = new BankLogInfo();
			if (FMHelper.hasNumber(ctx, info, companyId))
				info.setNumber(FMHelper.getNumberSilent(ctx, info, companyId));
			info.setCompany(currentCompany);
			info.setTime(Calendar.getInstance().getTime());
			info.setBizDate(Calendar.getInstance().getTime());
			info.setBankLogType(BankLogTypeEnum.agentPayBill);
			info.setPayAcnt(SubstitutingInfo.getPayAccount().getName());
			info.setPayeeAcnt(getAgentPayBillPayeeAcnt(SubstitutingInfo));
			BankLogSubstitutingSendInfo substituingSendInfo = new BankLogSubstitutingSendInfo();
			substituingSendInfo.setPaymentInfos(paymentInfos);
			substituingSendInfo.setBankAgentPayBillInfo(SubstitutingInfo);
			info.setSendInfo(getSerialValue(substituingSendInfo));
			// 保存银企日志信息
			pk = banklog.addnew(info);
		} catch (Exception e) {
			if (logger.isInfoEnabled())
				logger.info(e.getMessage());
		}
		return pk;
	}

	/**
	 * 描述：封装银行日记账的信息 作者：mmw 创建日期：2012-10-23-下午03:04:51
	 * 
	 * @param info
	 * @return
	 */
	private byte[] getSerialValue(Object info) {
		SectionByteOutputStream bytes = new SectionByteOutputStream();
		byte data[] = null;
		try {
			ObjectOutputStream out = new ObjectOutputStream(bytes);
			out.writeObject(info);
			out.close();
			data = ZipUtil.pack(bytes);
		} catch (IOException e) {
			if (logger.isInfoEnabled())
				logger.info(e.getMessage());
		} finally {
			try {
				bytes.close();
			} catch (IOException e) {
				if (logger.isInfoEnabled())
					logger.info(e.getMessage());
			}
		}
		return data;
	}

	/**
	 * 描述：拼接分录中所有的银行账号，个数大于250后省略
	 * 
	 * @param info
	 * @return
	 */
	private String getAgentPayBillPayeeAcnt(SubstitutingInfo info) {
		StringBuffer strBuff = new StringBuffer();
		for (int i = 0; i < info.getEntrys().size(); i++) {
			SubstitutingEntryInfo entryInfo = info.getEntrys().get(i);
			if (entryInfo != null)
				strBuff.append(entryInfo.getPayeeNumber() + ";");
			if (strBuff.length() >= 250)
				strBuff.append("...");
		}
		return strBuff.toString();
	}

	/**
	 * 描述：拼接分录中所有的银行账号，个数大于250后省略 作者：mmw 创建日期：2012-10-23-下午03:06:34
	 * 
	 * @param info代发单实体
	 * @return
	 */
	private String getPrivatePayAcnt(SubstitutingInfo info) {
		StringBuffer strBuff = new StringBuffer();
		if (info.getPayBankNumber() != null)
			strBuff.append(info.getPayBankNumber().getName() + ";");
		if (strBuff.length() >= 250)
			strBuff.append("...");
		return strBuff.toString();
	}

	/**
	 * 描述：拼接分录中所有的银行账号，个数大于250后省略 作者：mmw 创建日期：2012-10-23-下午03:08:05
	 * 
	 * @param info实体
	 * @param entryinfo分录
	 * @return
	 */
	private String getPrivatePayeeAcnt(SubstitutingInfo info, SubstitutingEntryInfo entryinfo) {
		StringBuffer strBuff = new StringBuffer();
		if (info.getPayBankNumber() != null)
			strBuff.append(entryinfo.getPayeeNumber() + ";");
		if (strBuff.length() >= 250)
			strBuff.append("...");
		return strBuff.toString();
	}

	/**
	 * 描述：更新代发单分录银行状态 作者：mmw 创建日期：2012-10-23-下午03:08:05
	 * 
	 * @param ctx
	 * @param info实体
	 * @param paymentInfos提交银企互联的封装参数
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void reverseBankAgentPayingBill(Context ctx, SubstitutingInfo info, PaymentInfo paymentInfos[]) throws BOSException, EASBizException {
		// 循环更新分录的银行状态和返回银行信息
		for (int i = 0; i < info.getEntrys().size(); i++) {
			BankPayingBillStateEnum state = FmBeHelper.transferState(paymentInfos[i].getState());
			String responseMessage = "";
			if (paymentInfos[i].getResponse() != null)
				responseMessage = paymentInfos[i].getResponse().getResponseMessage();
			SubstitutingEntryInfo entry = info.getEntrys().get(i);
			entry.setBankStatus(state);
			entry.setBankReturnInfo(responseMessage);
		}
		// 最后将分录的所有信息一起保存
		SubstitutingFactory.getLocalInstance(ctx).update(new ObjectUuidPK(info.getId().toString()), info);
	}

	/**
	 * 描述：更新代发单分录银行状态 作者：mmw 创建日期：2012-10-23-下午03:08:05
	 * 
	 * @param ctx
	 * @param serialnumber
	 *            分录的流水号
	 * @param info实体
	 * @param paymentInfos提交银企互联的参数
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void reverseBillState(Context ctx, BankPayingBillStateEnum state, String returnmessage, SubstitutingEntryInfo entryinfo, String serialnumber) throws BOSException,
			EASBizException {
		// 更新分录的银行状态和银行返回信息和分录的流水号
		entryinfo.setBankStatus(state);
		entryinfo.setBankReturnInfo(returnmessage);
		entryinfo.setSerialNumber(serialnumber);
		SelectorItemCollection item = new SelectorItemCollection();
		item.add(new SelectorItemInfo("bankStatus"));
		item.add(new SelectorItemInfo("bankReturnInfo"));
		item.add(new SelectorItemInfo("serialNumber"));
		ISubstitutingEntry.updatePartial(entryinfo, item);
	}

	/**
	 * 描述：调用工资批量支付接口时所需传的封装参数//此方法作废，这个是同行支付即调用的系统标准方法 作者：mmw
	 * 创建日期：2012-10-23-下午03:12:15
	 * 
	 * @param ctx
	 * @param payBankAcnt2
	 * @param info实体
	 * @param entryInfo分录实体
	 * @return 提交银企互联的封装参数
	 * @throws BOSException
	 * @throws EASBizException
	 * @throws RemoteException
	 * @throws ServiceException
	 */
	private PaymentInfo parseAgentPayInfo(Context ctx, SubstitutingInfo info, SubstitutingEntryInfo entryInfo, BankAcnt payBankAcnt2) throws BOSException, EASBizException,
			RemoteException, ServiceException {
		BankAcnt payBankAcnt = payBankAcnt2;// createAgentPayBankAcnt(ctx,
		// info.getPayBankNumber());
		BankAcnt recBankAcnt = createAgentRecBankAcnt(ctx, entryInfo);
		PaymentInfo paymentInfo = new PaymentInfo();
		paymentInfo.setBankAcnt(payBankAcnt);
		paymentInfo.setOppBankAcnt(recBankAcnt);
		if (info.getCurrency() == null) {
			throw new BEException(BEException.COMMON, new Object[] { "币别不能为空，并且只支持人民币付款" });
		}
		String currency = getCurrency(ctx, currencyInfo);
		// 币别
		paymentInfo.setCurrency(currency);
		// 分录金额
		paymentInfo.setAmount(entryInfo.getAmount());
		if (!FMHelper.isEmpty(info.getUsage()))
			// 用途
			paymentInfo.setUse(info.getUsage());
		else if (!FMHelper.isEmpty(entryInfo.getCostType()))
			// 费用类型
			paymentInfo.setUse(entryInfo.getCostType());
		// 业务系统用于标识一笔支付的唯一ID不能重复
		paymentInfo.setPackageID(entryInfo.getSerialNumber());
		// 同城异地
		paymentInfo.setSameCity(entryInfo.getDifPlace().getValue() == 0);
		// 提交银企时间
		paymentInfo.setSubmitDate(Calendar.getInstance().getTime());
		// 提交银企用户
		paymentInfo.setSubmiterID(userId);
		paymentInfo.setState(PaymentState.WILLSUBMIT);
		Timestamp time = new Timestamp(Calendar.getInstance().getTimeInMillis());
		// 预订时间为当前时间
		paymentInfo.setBookingDate(time);
		return paymentInfo;
	}

	/**
	 * 描述：包装付款账户参数 作者：mmw 创建日期：2012-10-23-下午03:13:43
	 * 
	 * @param ctx
	 * @param accountBank付款账号
	 * @return付款账户的封装参数
	 * @throws EASBizException
	 * @throws BOSException
	 */
	public static BankAcnt createAgentPayBankAcnt(Context ctx, AccountBankInfo accountBank) throws EASBizException, BOSException {
		AccountBankInfo payAccountBank = accountBank;
		com.kingdee.bos.dao.IObjectPK pk = new ObjectUuidPK(payAccountBank.getId());
		SelectorItemCollection selector = new SelectorItemCollection();
		selector.add("*");
		selector.add("openArea.name");
		selector.add("openArea.province");
		selector.add("openArea.number");
		selector.add("openArea.deptID");
		payAccountBank = AccountBankFactory.getLocalInstance(ctx).getAccountBankInfo(pk, selector);
		BankAcnt bankAcnt = new BankAcnt();
		// 校验付款账号的银行接口不能为空
		if (payAccountBank.getBankInterfaceType() == null)
			throw new BEException(BEException.BANKINTERFACE);
		// 银行接口值
		bankAcnt.setBank(payAccountBank.getBankInterfaceType().getAlias());
		// 银行账号
		bankAcnt.setAcntNumber(payAccountBank.getBankAccountNumber());
		// 账户名称
		bankAcnt.setAcntName(payAccountBank.getAcctName());
		// 设置银行证书和银行版本
		BankFacadeHelper.setBankAccountVersionAndCert(ctx, payAccountBank, bankAcnt);
		// 国家，默认中国
		bankAcnt.setCountry(EASResource.getString("com.kingdee.eas.fm.be.BEAutoGenerateResource", "7_BankFacadeControllerBean"));
		// 设置省和城市
		setPayerProviceAndCity(payAccountBank, bankAcnt);
		if (payAccountBank != null) {
			// 账户地区编码
			bankAcnt.setBranchID(payAccountBank.getOpenArea().getNumber());
			// 账户地区机构号
			bankAcnt.setDeptID(payAccountBank.getOpenArea().getDeptID());
			// 账户名称
			bankAcnt.setAcntName(payAccountBank.getAcctName());
		}
		return bankAcnt;
	}

	/**
	 * 描述：填充银行具体信息 作者：mmw 创建日期：2012-10-23-下午03:14:32
	 * 
	 * @param ctx
	 * @param entryInfo分录实体
	 * @return收款账户的封装参数
	 * @throws BEException
	 */
	private BankAcnt createAgentRecBankAcnt(Context ctx, SubstitutingEntryInfo entryInfo) throws BEException {
		BankAcnt bankAcnt = new BankAcnt();
		String recAccountBank = entryInfo.getPayeeNumber();
		if (entryInfo.getPayeeArea() != null) {
			bankAcnt.setBranchID(entryInfo.getPayeeArea().getNumber());
			bankAcnt.setDeptID(entryInfo.getPayeeArea().getDeptID());
		}
		// 支付银行
		bankAcnt.setBank(entryInfo.getPayeeBank());
		// 支付银行账号
		bankAcnt.setAcntNumber(recAccountBank);
		// 支付银行名
		bankAcnt.setAcntName(entryInfo.getPayeeName());
		bankAcnt.setCountry(EASResource.getString("com.kingdee.eas.fm.be.BEAutoGenerateResource", "7_BankFacadeControllerBean"));
		// 分录省份
		bankAcnt.setProvince(entryInfo.getPayeeProvince());
		// 分录城市
		bankAcnt.setCity(entryInfo.getPayeeCity().getName());
		return bankAcnt;
	}

	/**
	 * 描述：设置省份和城市 作者：mmw 创建日期：2012-10-23-下午03:15:22
	 * 
	 * @param payAccountBank收款账号
	 * @param payBankAcnt收款账户的封装参数
	 * @throws BEException
	 */
	public static void setPayerProviceAndCity(AccountBankInfo payAccountBank, BankAcnt payBankAcnt) throws BEException {
		if (payAccountBank.getOpenArea() == null) {
			throw new BEException(BEException.PAYERAREAISNULL);
		} else {
			String provice = payAccountBank.getOpenArea().getProvince();
			// 省
			payBankAcnt.setProvince(provice);
			String city = payAccountBank.getOpenArea().getName();
			// 城市
			payBankAcnt.setCity(city);
		}
	}

	/**
	 * 描述：转换币别为字符串 作者：mmw 创建日期：2012-10-23-下午03:17:59
	 * 
	 * @param ctx
	 * @param oldCurrency币别实体
	 * @return返回币别的英文简写
	 * @throws BEException
	 * @throws RemoteException
	 * @throws ServiceException
	 */
	public static String getCurrency(Context ctx, CurrencyInfo oldCurrency) throws BEException, RemoteException, ServiceException {
		if (oldCurrency == null)
			throw new BEException(BEException.CURRENCYISERROR, new Object[] { " " });
		String currencyCode = " ";
		if ("RMB".equalsIgnoreCase(oldCurrency.getIsoCode()))
			currencyCode = "CNY";
		else
			currencyCode = oldCurrency.getIsoCode().toUpperCase();
		return currencyCode;
	}

	/**
	 * 描述：按单据同步银行付款单状态 作者：mmw 创建日期：2012-10-23-下午03:18:45
	 * 
	 * @see com.kingdee.eas.custom.yq.df.app.AbstractSubstitutingControllerBean#_syncBankAgentPayStateByBill(com.kingdee.bos.Context,
	 *      java.util.List)
	 * @param ctx
	 * @param ids代发单实体id
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected void _syncBankAgentPayStateByBill(Context ctx, List ids) throws BOSException, EASBizException {
		EntityViewInfo ev = new EntityViewInfo();
		FilterInfo filter = new FilterInfo();
		filter.getFilterItems().add(new FilterItemInfo("id", new HashSet(ids), CompareType.INCLUDE));
		ev.setFilter(filter);
		ev.getSelector().add("*");
		ev.getSelector().add("entrys.*");
		ev.getSelector().add("feeType.number");
		ev.getSelector().add("payBankNumber.*");
		ev.getSelector().add("payBankNumber.openArea.*");
		ev.getSelector().add("payBankNumber.bankInterfaceType");
		ev.getSelector().add("entrys.SettlementType.*");

		SubHelp subhelp = new SubHelp();
		// 声明代发单接口
		ISubstituting ISubstitutings = SubstitutingFactory.getLocalInstance(ctx);
		// 声明代发单辅助功能接口
		IAuxiliaryFunction auxiliaryFunctions = AuxiliaryFunctionFactory.getLocalInstance(ctx);
		// 声明银企日志接口
		IBankLogFacade bankLogFacades = BankLogFacadeFactory.getLocalInstance(ctx);
		// 结算方式接口
		ISettlementType settlementTypecoll = SettlementTypeFactory.getLocalInstance(ctx);
		// 根据id查出代发单集合
		SubstitutingCollection billColl = ISubstitutings.getSubstitutingCollection(ev);
		BankAcnt payBankAcnt = null;
		String packageID = null;
		// 对 每一个账户循环更新
		for (int i = 0, size = billColl.size(); i < size; i++) {
			SubstitutingInfo bill = billColl.get(i);
			// "交易成功，交易失败状态的的银行代发单不允许同步状态！
			// 若分录中没有一条银行状态满足条件，则不需要掉用一下接口,若有则返回false
			if (checkEntryPayState(bill))
				return;
			AccountBankInfo accountBankInfo = null;
			accountBankInfo = bill.getPayBankNumber();// 付款账号
			BankInterfaceTypeEnum bankInterface = accountBankInfo.getBankInterfaceType();// 银行接口

			// 付款账号的封装实体信息
			payBankAcnt = new BankAcnt();
			payBankAcnt.setBank(bankInterface.getAlias());
			payBankAcnt.setAcntNumber(accountBankInfo.getBankAccountNumber());
			payBankAcnt.setAcntName(accountBankInfo.getAcctName());
			// R090616-165 多证书版本时传递“银行版本”“银行证书”给网关
			BankFacadeHelper.setBankAccountVersionAndCert(ctx, accountBankInfo, payBankAcnt);

			if (accountBankInfo.getOpenArea() != null) {
				payBankAcnt.setProvince(accountBankInfo.getOpenArea().getProvince());
				payBankAcnt.setCity(accountBankInfo.getOpenArea().getName());
				// todo: 添加几行 设置付款账户的brankId;
				payBankAcnt.setBranchID(accountBankInfo.getOpenArea().getNumber());
				payBankAcnt.setDeptID(accountBankInfo.getOpenArea().getDeptID());
			}

			// "交易成功，交易失败状态的的银行代发单不允许同步状态！
			// 若分录满足条件的记录在list集合中
			List list = getEntryPayState(bill);
			// 工资跨行付款/亲情1+1跨行付款/代收货款---调用付款单对私对公批量按单据同步接口
			PayStateInfo[] PayStateInfoColl;
			PayStateInfo info = null;
			int type = 0;
			IObjectPK pk = null;
			String feeTypeNumber = bill.getFeeType().getNumber();// 收付类别编码
			if (feeTypeNumber.equals(ConstantValueUtil.WAGES) || feeTypeNumber.equals(ConstantValueUtil.KINGSHIPBILL)) {
				// 工资同行付款/亲情1+1同行付款--调用代发单对私批量按单据同步接口
				try {
					String[] packageIds = new String[list.size()];
					for (int j = 0; j < list.size(); j++) {
						packageIds[j] = ((SubstitutingEntryInfo) list.get(j)).getSerialNumber();
					}
					BankBatchSalaryService bankBatchSalaryService = new BankBatchSalaryService(ctx);
					// 调用按单据同步状态接口
					PayStateInfoColl = bankBatchSalaryService.getSalaryPaymentState(createCaller(), payBankAcnt, packageIds);
					if (PayStateInfoColl == null) {
						continue;
					}
					// 暂时只取一个返回值，要么全部成功，要么全部失败
					for (int r = 0; r < list.size(); r++) {
						SubstitutingEntryInfo entryinfo = (SubstitutingEntryInfo) list.get(r);
						BankPayingBillStateEnum state = FmBeHelper.transferState(((PayStateInfo) PayStateInfoColl[r]).getPaymentState());
						entryinfo.setBankStatus(state);
						String returnMsg = ((PayStateInfo) PayStateInfoColl[r]).getReturnMessage();
						entryinfo.setBankReturnInfo(returnMsg);
						// 反写上游单据付款状态及更新代发单数据
						reverseSourceBillState(ctx, entryinfo);
						// 提交银企互联成功时记录在代发单辅助功能中
						subhelp.LogForAuxiliaryFunction(ctx, bill, InterfaceTypeEnum.BACKMSG, entryinfo, auxiliaryFunctions, "", "");
					}
				} catch (Exception e) {
					logger.error("sync substituting failure! exception message is:", e);
					throw new BEException(BEException.SYNCFAILURE, new Object[] { e.getMessage() });
				}
			} else if (feeTypeNumber.equals(ConstantValueUtil.WAGESN) || feeTypeNumber.equals(ConstantValueUtil.KINGSHIPBILLN)
					|| feeTypeNumber.equals(ConstantValueUtil.REMITREFUNDBILL)) {
				// 工资跨行付款/亲情1+1跨行付款/代收货款---调用付款单对私对公批量按单据同步接口
				try {
					String[] packageIds = new String[1];
					for (int k = 0; k < list.size(); k++) {
						SubstitutingEntryInfo entryInfo = (SubstitutingEntryInfo) list.get(k);
						packageIds[0] = ((SubstitutingEntryInfo) list.get(k)).getSerialNumber();
						// 生成银企日志，返回主键pk
						pk = bankLogFacades.buildPayStateSend(entryInfo.getSettlementType().isIsPersonPay(), payBankAcnt, packageIds, accountBankInfo);

						// 如果是对公付款，则调用接口getPaymentState,如果是对私付款，
						// 则调用接口getPaymentStatePrivate
						SettlementTypeInfo settlementTypeinfo = settlementTypecoll.getSettlementTypeInfo(new ObjectUuidPK(entryInfo.getSettlementType().getId()));
						if (!settlementTypeinfo.isIsPersonPay()) {
							BankServiceUtil bankServiceUtil = new BankServiceUtil(ctx);
							PayStateInfoColl = bankServiceUtil.getPaymentState(createCaller(), payBankAcnt, packageIds);
						} else {
							BankPrivateService bankPrivateUtil = new BankPrivateService(ctx);
							PayStateInfoColl = bankPrivateUtil.getPaymentStatePrivate(createCaller(), payBankAcnt, packageIds);
						}
						type = 1;
						if (PayStateInfoColl == null) {
							continue;
						}

						// 根据主键pk更新银企日志
						bankLogFacades.buildPayStateReceive(pk, info);
						BankPayingBillStateEnum returnMsgstate = FmBeHelper.transferState(((PayStateInfo) PayStateInfoColl[0]).getPaymentState());
						String returnMsg = ((PayStateInfo) PayStateInfoColl[0]).getReturnMessage();
						entryInfo.setBankStatus(returnMsgstate);
						entryInfo.setBankReturnInfo(returnMsg);
						// 修改分录的银行状态，银行返回信息，若交易成功则实发金额，实发笔数，
						reverseSourceBillState(ctx, entryInfo);
						// 提交银企互联成功时记录在代发单辅助功能中
						subhelp.LogForAuxiliaryFunction(ctx, bill, InterfaceTypeEnum.BACKMSG, entryInfo, auxiliaryFunctions, "", "");
					}
				} catch (Exception e) {
					logger.error("sync Substituting failure! exception message is:", e);
					// 根据主键pk更新银企日志
					bankLogFacades.buildException(pk, e, type);
					throw new BEException(BEException.SYNCFAILURE, new Object[] { e.getMessage() });
				}
			}
		}
	}

	/**
	 * 描述：若分录满足条件的记录在list集合中 作者：mmw 创建日期：2012-10-19-上午10:41:46
	 * 
	 * @param bill
	 * @return 符合条件的代发单实体信息
	 */
	private List getEntryPayState(SubstitutingInfo bill) {
		List list = new ArrayList();
		SubstitutingEntryCollection coll = bill.getEntrys();
		for (int i = 0; i < coll.size(); i++) {
			BankPayingBillStateEnum state = ((SubstitutingEntryInfo) (coll.get(i))).getBankStatus();
			// 准备提交,交易未确认，提交失败，提交成功，允许同步状态
			if (state == BankPayingBillStateEnum.NC || state == BankPayingBillStateEnum.OF || state == BankPayingBillStateEnum.OS || state == BankPayingBillStateEnum.OP) {
				list.add(bill.getEntrys().get(i));
			}
		}
		return list;
	}

	/**
	 * 描述：描述：检查分录中的银行状态是否有’交易未确认‘，有则返回false 准备提交，交易成功，交易失败状态的的银行代发单不允许同步状态！
	 * 作者：mmw 创建日期：2012-10-23-下午03:24:25
	 * 
	 * @param bill代发单实体信息
	 * @return若有代发单符合条件则返回false，反之true
	 */
	private boolean checkEntryPayState(SubstitutingInfo bill) {
		for (int i = 0; i < bill.getEntrys().size(); i++) {
			BankPayingBillStateEnum state = ((SubstitutingEntryInfo) (bill.getEntrys().get(i))).getBankStatus();
			// 准备提交,交易未确认，提交失败，提交成功，允许同步状态
			if (state == BankPayingBillStateEnum.NC || state == BankPayingBillStateEnum.OF || state == BankPayingBillStateEnum.OS || state == BankPayingBillStateEnum.OP) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 描述：接口连接参数
	 * 
	 * @return
	 */
	private CallerTag createCaller() {
		CallerTag caller = new CallerTag();
		caller.setCaller("Jason");
		caller.setIp("127.0.0.1");
		caller.setOs("EAS");
		caller.setVersion("6.0");
		caller.setTime(new Date());
		return caller;
	}

	/**
	 * 描述：更新代发单主表和分录的数据 作者：mmw 创建日期：2012-10-23-下午03:26:19
	 * 
	 * @param ctx
	 * @param info代发单分录实体信息
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private void reverseSourceBillState(Context ctx, SubstitutingEntryInfo info) throws BOSException, EASBizException {
		BankPayingBillStateEnum state = info.getBankStatus();
		// 更新主表实发金额,实发笔数
		// 更新分录银行状态,银行返回信息,是否成功
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			conn = getConnection(ctx);
			// 更新主表代发单实发金额和实发笔数
			String sql = "Update CT_YQ_Substituting SET CFFactAmount= CFFactAmount + ?,CFFactPenNumber=CFFactPenNumber + ? where fid  = ? ";
			pstmt = conn.prepareStatement(sql);
			boolean isSuccess = false;
			// 银行状态交易成功的情况
			if (state.equals(BankPayingBillStateEnum.TS)) {
				isSuccess = true;
				pstmt.setBigDecimal(1, info.getAmount());
				pstmt.setInt(2, 1);
			} else {
				isSuccess = false;
				pstmt.setBigDecimal(1, FMConstants.ZERO);
				pstmt.setInt(2, FMConstants.INT_ZERO);
			}
			pstmt.setString(3, info.getParent().getId().toString());
			pstmt.executeUpdate();
			// 更新分录银行状态和银行返回信息，并且更新是否成功字段
			sql = "Update CT_YQ_SubstitutingEntry set CFBankStatus = ?,CFBankReturnInfo = ?,CFIsSucceed = ? where fid  = ? ";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, state.getValue());
			pstmt.setString(2, info.getBankReturnInfo());
			pstmt.setBoolean(3, isSuccess);
			pstmt.setString(4, info.getId().toString());
			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new BEException(BEException.WRITESTATEFAILURE);
		} finally {
			SQLUtils.cleanup(null, pstmt, conn);
		}
	}

	/**
	 * 描述：补登日记账 提交银企以后，如果银行返回的状态时未确认，则代发单的实际付款金额不会更新，所以不会登记日记账。
	 * 首先删除有问题的日记账，再按照实发金额登日记账。 作者：mmw 创建日期：2012-10-22-下午03:24:36
	 * 
	 * @see com.kingdee.eas.custom.yq.df.app.AbstractSubstitutingControllerBean#_registerJournal(com.kingdee.bos.Context,
	 *      java.util.Set)
	 * @param ctx
	 * @param idSet
	 *            代发单id集合
	 * @return
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected Map _registerJournal(Context ctx, Set idSet) throws BOSException, EASBizException {
		String ids = SubHelp.setTran2String(idSet);
		Map resultMap = new HashMap();
		String validId = "";
		Set validSet = new HashSet();
		Set idSetForSqlNoJournalFinal = new HashSet();

		// 查询已经生成了日记账，但是金额不正确的代发单的id
		String sqlAmountNotEquals = "select ap.fid as agentpaybillid from CT_YQ_Substituting ap " + "LEFT JOIN T_CAS_JOURNAL j ON ap.fid=j.fbillid where ap.cffactAmount <> 0 "
				+ "and ap.cffactAmount <> j.fcreditamount and ap.fid in (" + ids + ")";
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		Iterator itForIdSet = null;
		try {
			// 获取已经生成日记账，并且可以补登日记账的代发单id
			conn = getConnection(ctx);
			pstmt = conn.prepareStatement(sqlAmountNotEquals);
			// 将ids中的问号赋值
			pstmt = SubHelp.setSql(idSet, pstmt, 1);
			rs = pstmt.executeQuery();
			while (rs.next()) {
				// 获取已经生成日记账的代发单id
				validId = rs.getString("agentpaybillid");
				validSet.add(validId);
				idSet.remove(validId);
			}

			// 查询已经生成日记账的代发单的id集合
			ids = SubHelp.setTran2String(idSet);
			String sqlNoJournal = "select fbillid from T_CAS_JOURNAL WHERE fbilltype=40 and fbillid in (" + ids + ")";
			pstmt = conn.prepareStatement(sqlNoJournal);
			// 将ids中的问号赋值
			pstmt = SubHelp.setSql(idSet, pstmt, 1);
			rs = pstmt.executeQuery();
			itForIdSet = idSet.iterator();
			while (itForIdSet.hasNext()) {
				idSetForSqlNoJournalFinal.add(itForIdSet.next());
			}
			while (rs.next()) {
				validId = rs.getString("fbillid");
				idSetForSqlNoJournalFinal.remove(validId);
			}

			// idSet中的id只剩下未生成日记账的代发单的id，如果这些代发单的实发金额不为0，
			// 则可以补登日记账
			ids = SubHelp.setTran2String(idSetForSqlNoJournalFinal);
			String sqlNoJournalFinal = "select fid from CT_YQ_Substituting where cffactAmount <> 0 and fid in (" + ids + ")";
			pstmt = conn.prepareStatement(sqlNoJournalFinal);
			// 将ids中的问号赋值
			pstmt = SubHelp.setSql(idSetForSqlNoJournalFinal, pstmt, 1);
			rs = pstmt.executeQuery();
			while (rs.next()) {
				validId = rs.getString("fid");
				validSet.add(validId);
				idSet.remove(validId);
			}

			// 先删除日记账
			String validIds = SubHelp.setTran2String(validSet);
			String sql = "DELETE from T_CAS_JOURNAL where FBILLTYPE = 40 AND FBILLID IN (" + validIds + ")";
			pstmt = conn.prepareStatement(sql);
			// 将ids中的问号赋值
			pstmt = SubHelp.setSql(validSet, pstmt, 1);
			pstmt.execute();
		} catch (SQLException e) {
			throw new BOSException(e);
		} finally {
			SQLUtils.cleanup(rs, pstmt, conn);
		}
		// 再登帐
		SubHelp subhelp = new SubHelp();
		subhelp.bookBatchSet(ctx, validSet);

		String successNumbers = "";
		String failedNumbers = "";
		if (validSet.size() != 0) {
			successNumbers = getAgentPayBillNumbers(ctx, validSet);
			failedNumbers = getAgentPayBillNumbers(ctx, idSet);
		}
		// 传回前台构造提示信息
		resultMap.put("successNumbers", successNumbers);
		resultMap.put("failedNumbers", failedNumbers);
		resultMap.put("successSize", new Integer(validSet.size()));
		resultMap.put("failedSize", new Integer(idSet.size()));
		return resultMap;
	}

	/**
	 * 描述：根据id获得单据编码 作者：mmw 创建日期：2012-10-22-下午05:34:48
	 * 
	 * @param ctx
	 * @param idSet
	 *            代发单id集合
	 * @return返回代发单编码
	 * @throws BOSException
	 * @throws EASBizException
	 */
	private String getAgentPayBillNumbers(Context ctx, Set idSet) throws BOSException, EASBizException {
		String ids = SubHelp.setTran2String(idSet);
		String sql = "select FNumber from CT_YQ_Substituting where fid in (" + ids + ")";
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuffer sb = new StringBuffer();
		try {
			conn = getConnection(ctx);
			pstmt = conn.prepareStatement(sql);
			// 将ids中的问号赋值
			pstmt = SubHelp.setSql(idSet, pstmt, 1);
			// 执行sql语句，获得数据集
			rs = pstmt.executeQuery();
			while (rs.next()) {
				sb.append(rs.getString("Fnumber")).append(",");
			}
		} catch (SQLException e) {
			throw new BOSException(e);
		} finally {
			SQLUtils.cleanup(rs, pstmt, conn);
		}
		return sb.toString();
	}

	/**
	 * 描述：修改分录状态 作者：mmw 创建日期：2012-10-22-下午04:49:30
	 * 
	 * @see com.kingdee.eas.custom.yq.df.app.AbstractSubstitutingControllerBean#_updateState(com.kingdee.bos.Context,
	 *      com.kingdee.bos.dao.IObjectPK[],
	 *      com.kingdee.eas.fm.be.BankPayingBillStateEnum)
	 * @param ctx
	 * @param pks分录主pk
	 * @param state分录的银行状态
	 * @return更新成功返回true，反之false
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected boolean _updateState(Context ctx, IObjectPK[] pks, BankPayingBillStateEnum state) throws BOSException, EASBizException {
		if (pks == null || pks.length == 0) {
			return false;
		}
		HashSet idSet = new HashSet();
		// 循环将pks赋值给idset集合中
		for (int i = 0; i < pks.length; i++) {
			idSet.add(pks[i].toString());
		}
		// 校验分录的银行状态的范围是否为交易成功或交易失败
		if (state.getValue() != BankPayingBillStateEnum.TS_VALUE && state.getValue() != BankPayingBillStateEnum.TF_VALUE) {
			throw new BEException(BEException.UPDATEBANKAGENTERROR1);
		}

		FilterInfo filter = new FilterInfo();
		filter.getFilterItems().add(new FilterItemInfo("id", idSet, CompareType.INCLUDE));
		EntityViewInfo evi = new EntityViewInfo();
		evi.setFilter(filter);
		evi.getSelector().add("parent");
		evi.getSelector().add("*");

		SubstitutingEntryCollection coll = SubstitutingEntryFactory.getLocalInstance(ctx).getSubstitutingEntryCollection(evi);
		for (int i = 0, size = coll.size(); i < size; i++) {
			SubstitutingEntryInfo entryinfo = coll.get(i);
			// 检验分录的银行状态是否为‘交易未确认’
			if (!entryinfo.getBankStatus().equals(BankPayingBillStateEnum.NC)) {
				throw new BEException(BEException.UPDATEBANKAGENTERROR);
			}
			entryinfo.setBankStatus(state);
			// 更新分录状态和主表的实发金额
			reverseSourceBillState(ctx, entryinfo);
		}
		return true;
	}

	/**
	 * 描述：修改状态后登银行日记账 作者：mmw 创建日期：2012-10-22-下午05:10:10
	 * 
	 * @see com.kingdee.eas.custom.yq.df.app.AbstractSubstitutingControllerBean#_registration(com.kingdee.bos.Context,
	 *      java.util.Set)
	 * @param ctx
	 * @param idSet代发单id集合
	 * @throws BOSException
	 * @throws EASBizException
	 */
	protected void _registration(Context ctx, Set idSet) throws BOSException, EASBizException {
		SubHelp subhelp = new SubHelp();
		subhelp.bookBatchSet(ctx, idSet);
	}

	/**
	 * 描述：修改源单据是否下推字段为未下推 作者：mmw 创建日期：2012-10-24-下午06:29:07
	 * 
	 * @see com.kingdee.eas.custom.yq.df.app.AbstractSubstitutingControllerBean#_updateSourceBill(com.kingdee.bos.Context,
	 *      java.lang.String, java.lang.String, java.lang.String, java.util.Set)
	 * @param ctx
	 * @param table工资
	 *            ,代收货款,亲情1+1
	 * @param pro需要修改字段名
	 * @param var字段值
	 * @param idSet表的id集合
	 * @throws BOSException
	 */
	protected void _updateSourceBill(Context ctx, Map map) throws BOSException, EASBizException {
		if (map == null) {
			return;
		}
		Set set1 = (Set) map.get("idset");
		List idlist = FMHelper.set2List(set1);
		int count = set1.size();
		// 除以size的整倍数
		int num1 = count / 1000;
		// 除以size的余数
		int num2 = count % 1000;
		// 标示num1大于零
		if (count > 1000) {
			// 将count分批次以size为单位数量提交
			for (int i = 0; i < num1; i++) {
				Set setid = new HashSet();
				for (int j = i * 1000; j < 1000 * (i + 1); j++) {
					setid.add(idlist.get(j));
				}
				updateSourid(ctx, map, setid);
			}
			// 若余数不为零,则表示除以size有余数,即把剩下的数量单子在此提交
			if (num2 != 0) {
				Set setid = new HashSet();
				for (int i = 1000 * num1; i < count; i++) {
					setid.add(idlist.get(i));
				}
				updateSourid(ctx, map, setid);
			}
		} else {
			updateSourid(ctx, map, set1);
		}
	}

	/**
	 * 描述： 作者：mmw 创建日期：2012-12-15-上午11:53:28
	 * 
	 * @param ctx
	 * @param map
	 * @param set1
	 * @throws SQLDataException
	 * @throws BEException
	 */
	private void updateSourid(Context ctx, Map map, Set set1) throws SQLDataException, BEException {
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			conn = getConnection(ctx);
			// 更新主表代发单//此为?,?,.....
			String ids = SubHelp.setTran2String(set1);
			// “付款日期”“支付方式”“付款银行”“付款账号”“是否下推代发单”
			//工资CFPayDate,CFPayment,CFPaymentbankID,CFPaymentAccount,CFWhesingle
			// 亲情CFPayDate,CFPayType,CFPayBank,CFPayAccountID,CFIscreatePayment
			// 代收CFRemitDate,CFPayment,CFPayingBankID,CFPayingAccountID,
			// CFIsCreateRepBill
			String sql = "";
			if (ConstantValueUtil.TABLE_WAGES.equals(map.get("table"))) {
				// 工资sdl
				sql = "UPDATE " + map.get("table") + " SET " + map.get("property1") + " = ?," + map.get("property2") + "=''," + map.get("property3") + "='',"
						+ map.get("property4") + "=''," + map.get("property5") + "=''," + map.get("property6") + "='' WHERE FID IN (" + ids + ")";
			} else {
				// 代收货款 亲情1+1
				sql = "UPDATE " + map.get("table") + " SET " + map.get("property1") + " = ?," + map.get("property2") + "=''," + map.get("property3") + "='',"
						+ map.get("property4") + "=''," + map.get("property5") + "='' WHERE FID IN (" + ids + ")";
			}
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, map.get("value").toString());
			// 拼接ids语句,并赋值
			pstmt = SubHelp.setSql(set1, pstmt, 2);
			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new BEException(BEException.COMMON, new Object[] { e.getMessage() });
		} finally {
			SQLUtils.cleanup(null, pstmt, conn);
		}
	}
}